commit
030d4ec94c
@ -0,0 +1,75 @@
|
|||||||
|
# PowerShell (Sapian) — SSH tipo Linux + Backup/Restore
|
||||||
|
|
||||||
|
Este repositorio contiene los scripts para dejar PowerShell en Windows listo para trabajar como en Ubuntu:
|
||||||
|
|
||||||
|
✅ Autosugerencias de comandos (tipo fish)
|
||||||
|
✅ Búsqueda en historial con `Ctrl+R` (fzf)
|
||||||
|
✅ Conexiones SSH rápidas usando tu `ssh_config` existente
|
||||||
|
✅ Backup y restore del entorno (incluye llaves si aplica)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Estructura del repo
|
||||||
|
|
||||||
|
PowerShell/
|
||||||
|
│ README.md
|
||||||
|
└─ scripts/
|
||||||
|
│ 01-New-SshConfigLink.ps1
|
||||||
|
│ 02-Backup-PwshSshSetup.ps1
|
||||||
|
│ 03-Restore-PwshSshSetup.ps1
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## IMPORTANTE: ubicación real del ssh_config
|
||||||
|
|
||||||
|
El archivo con los servidores **NO está dentro de este repo**.
|
||||||
|
|
||||||
|
Se mantiene en esta ruta (NO se mueve):
|
||||||
|
|
||||||
|
C:\Users\ofgar\Workspace\revelation\ssh_config
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ¿Qué hace cada script?
|
||||||
|
|
||||||
|
### `01-New-SshConfigLink.ps1`
|
||||||
|
Crea el enlace para que Windows use tu ssh_config actual:
|
||||||
|
|
||||||
|
C:\Users\ofgar.ssh\config --> C:\Users\ofgar\Workspace\revelation\ssh_config
|
||||||
|
|
||||||
|
|
||||||
|
Opcional: también puede reparar permisos de `id_rsa` si da error de permisos.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `02-Backup-PwshSshSetup.ps1`
|
||||||
|
Genera un backup del entorno:
|
||||||
|
|
||||||
|
- Perfil de PowerShell
|
||||||
|
- Historial de comandos (PSReadLine)
|
||||||
|
- Copia del `ssh_config` (desde su ruta actual)
|
||||||
|
- Opcional: llaves SSH (`id_rsa`, `id_rsa.pub`, `known_hosts`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `03-Restore-PwshSshSetup.ps1`
|
||||||
|
Restaura todo en un equipo nuevo:
|
||||||
|
|
||||||
|
- Instala módulos necesarios
|
||||||
|
- Restaura perfil PowerShell
|
||||||
|
- Restaura historial (opcional)
|
||||||
|
- Restaura llaves + repara permisos (opcional)
|
||||||
|
- Vuelve a crear el enlace de `~\.ssh\config`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Instalación base (una sola vez)
|
||||||
|
|
||||||
|
Abrir PowerShell y ejecutar:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Install-Module PSReadLine -Scope CurrentUser -Force
|
||||||
|
winget install fzf
|
||||||
|
Install-Module PSFzf -Scope CurrentUser -Force
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
<#
|
||||||
|
Crea el link: C:\Users\ofgar\.ssh\config -> (ruta actual de ssh_config)
|
||||||
|
Opcional: repara permisos de la llave id_rsa (ACL) para evitar "permissions too open".
|
||||||
|
#>
|
||||||
|
|
||||||
|
param(
|
||||||
|
[string]$RepoConfig = "C:\Users\ofgar\Workspace\revelation\ssh_config",
|
||||||
|
[switch]$FixKeyPermissions
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$userSshDir = Join-Path $env:USERPROFILE ".ssh"
|
||||||
|
$userConfig = Join-Path $userSshDir "config"
|
||||||
|
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||||
|
|
||||||
|
function Backup-File([string]$Path) {
|
||||||
|
if (Test-Path -LiteralPath $Path) {
|
||||||
|
$bak = "$Path.bak.$timestamp"
|
||||||
|
Copy-Item -LiteralPath $Path -Destination $bak -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Repair-PrivateKeyAcl([string]$KeyPath) {
|
||||||
|
if (-not (Test-Path -LiteralPath $KeyPath)) { return }
|
||||||
|
icacls $KeyPath /inheritance:r | Out-Null
|
||||||
|
icacls $KeyPath /grant:r "$($env:USERNAME):F" | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validar origen
|
||||||
|
if (-not (Test-Path -LiteralPath $RepoConfig)) {
|
||||||
|
throw "No existe el ssh_config en: $RepoConfig"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Asegurar .ssh
|
||||||
|
New-Item -ItemType Directory -Force -Path $userSshDir | Out-Null
|
||||||
|
|
||||||
|
# Si existe config, manejarlo
|
||||||
|
if (Test-Path -LiteralPath $userConfig) {
|
||||||
|
$item = Get-Item -LiteralPath $userConfig -Force
|
||||||
|
$isLink = $null -ne $item.LinkType
|
||||||
|
|
||||||
|
if ($isLink) {
|
||||||
|
try {
|
||||||
|
if ($item.Target -eq $RepoConfig) {
|
||||||
|
Write-Host "OK: ya está enlazado -> $RepoConfig"
|
||||||
|
} else {
|
||||||
|
Remove-Item -LiteralPath $userConfig -Force
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Remove-Item -LiteralPath $userConfig -Force
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Backup-File $userConfig
|
||||||
|
Remove-Item -LiteralPath $userConfig -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Crear symlink (o fallback a copia)
|
||||||
|
if (-not (Test-Path -LiteralPath $userConfig)) {
|
||||||
|
try {
|
||||||
|
New-Item -ItemType SymbolicLink -Path $userConfig -Target $RepoConfig -Force | Out-Null
|
||||||
|
Write-Host "OK: config -> $RepoConfig"
|
||||||
|
} catch {
|
||||||
|
Write-Warning "No se pudo crear symlink. Se hará copia (NO queda sincronizado con el archivo original)."
|
||||||
|
Copy-Item -LiteralPath $RepoConfig -Destination $userConfig -Force
|
||||||
|
Write-Host "OK: config copiado desde $RepoConfig"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Reparar permisos de llave si se pide
|
||||||
|
if ($FixKeyPermissions) {
|
||||||
|
$key = Join-Path $userSshDir "id_rsa"
|
||||||
|
Repair-PrivateKeyAcl $key
|
||||||
|
Write-Host "OK: permisos ajustados para id_rsa"
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
<#
|
||||||
|
Backup del entorno PowerShell + SSH.
|
||||||
|
Incluye: perfil, historial PSReadLine, ssh_config (ruta actual) y opcional llaves.
|
||||||
|
#>
|
||||||
|
|
||||||
|
param(
|
||||||
|
[string]$RepoConfig = "C:\Users\ofgar\Workspace\revelation\ssh_config",
|
||||||
|
[string]$BackupRoot = (Join-Path $env:USERPROFILE "Documents\pwsh_ssh_backup"),
|
||||||
|
[switch]$IncludeKeys
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$ts = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||||
|
$dst = Join-Path $BackupRoot $ts
|
||||||
|
|
||||||
|
New-Item -ItemType Directory -Force -Path $dst | Out-Null
|
||||||
|
|
||||||
|
function SafeCopy([string]$src, [string]$name) {
|
||||||
|
if (Test-Path -LiteralPath $src) {
|
||||||
|
Copy-Item -LiteralPath $src -Destination (Join-Path $dst $name) -Force
|
||||||
|
Write-Host "OK: $name"
|
||||||
|
} else {
|
||||||
|
Write-Warning "No existe: $src"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1) Perfil PowerShell
|
||||||
|
SafeCopy $PROFILE "Microsoft.PowerShell_profile.ps1"
|
||||||
|
|
||||||
|
# 2) Historial PSReadLine
|
||||||
|
$hist = (Get-PSReadLineOption).HistorySavePath
|
||||||
|
SafeCopy $hist "ConsoleHost_history.txt"
|
||||||
|
|
||||||
|
# 3) ssh_config (ruta actual)
|
||||||
|
SafeCopy $RepoConfig "ssh_config"
|
||||||
|
|
||||||
|
# 4) Inventario de módulos
|
||||||
|
Get-InstalledModule | Select Name, Version | Sort Name |
|
||||||
|
Out-File (Join-Path $dst "pwsh_modules.txt") -Encoding UTF8
|
||||||
|
Write-Host "OK: pwsh_modules.txt"
|
||||||
|
|
||||||
|
# 5) Opcional: llaves y archivos SSH
|
||||||
|
if ($IncludeKeys) {
|
||||||
|
$sshDir = Join-Path $env:USERPROFILE ".ssh"
|
||||||
|
SafeCopy (Join-Path $sshDir "id_rsa") "id_rsa"
|
||||||
|
SafeCopy (Join-Path $sshDir "id_rsa.pub") "id_rsa.pub"
|
||||||
|
SafeCopy (Join-Path $sshDir "known_hosts") "known_hosts"
|
||||||
|
SafeCopy (Join-Path $sshDir "config") "config_current"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 6) Info general
|
||||||
|
$info = Join-Path $dst "env_info.txt"
|
||||||
|
"PowerShell: $($PSVersionTable.PSVersion)" | Out-File $info -Encoding UTF8
|
||||||
|
"PROFILE: $PROFILE" | Add-Content $info
|
||||||
|
"PSReadLineHistory: $hist" | Add-Content $info
|
||||||
|
"RepoConfig: $RepoConfig" | Add-Content $info
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Backup creado en: $dst"
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
<#
|
||||||
|
Restaura el entorno desde un backup:
|
||||||
|
- Perfil
|
||||||
|
- Historial (opcional)
|
||||||
|
- Llaves (opcional) + permisos id_rsa
|
||||||
|
- Re-crea el link ~/.ssh/config -> ssh_config (ruta actual)
|
||||||
|
#>
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$BackupPath,
|
||||||
|
|
||||||
|
[string]$RepoConfig = "C:\Users\ofgar\Workspace\revelation\ssh_config",
|
||||||
|
|
||||||
|
[switch]$RestoreHistory,
|
||||||
|
[switch]$RestoreKeys
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
function Repair-PrivateKeyAcl([string]$KeyPath) {
|
||||||
|
if (-not (Test-Path -LiteralPath $KeyPath)) { return }
|
||||||
|
icacls $KeyPath /inheritance:r | Out-Null
|
||||||
|
icacls $KeyPath /grant:r "$($env:USERNAME):F" | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1) Asegurar módulos
|
||||||
|
Install-Module PSReadLine -Scope CurrentUser -Force
|
||||||
|
Install-Module PSFzf -Scope CurrentUser -Force
|
||||||
|
|
||||||
|
# 2) Perfil
|
||||||
|
$profileSrc = Join-Path $BackupPath "Microsoft.PowerShell_profile.ps1"
|
||||||
|
if (Test-Path -LiteralPath $profileSrc) {
|
||||||
|
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $PROFILE) | Out-Null
|
||||||
|
Copy-Item -LiteralPath $profileSrc -Destination $PROFILE -Force
|
||||||
|
Write-Host "OK: Perfil restaurado"
|
||||||
|
} else {
|
||||||
|
Write-Warning "No se encontró perfil en el backup"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 3) Historial (opcional)
|
||||||
|
if ($RestoreHistory) {
|
||||||
|
$histDst = (Get-PSReadLineOption).HistorySavePath
|
||||||
|
$histSrc = Join-Path $BackupPath "ConsoleHost_history.txt"
|
||||||
|
if (Test-Path -LiteralPath $histSrc) {
|
||||||
|
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $histDst) | Out-Null
|
||||||
|
Copy-Item -LiteralPath $histSrc -Destination $histDst -Force
|
||||||
|
Write-Host "OK: Historial restaurado"
|
||||||
|
} else {
|
||||||
|
Write-Warning "No se encontró historial en el backup"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 4) Llaves (opcional)
|
||||||
|
if ($RestoreKeys) {
|
||||||
|
$sshDir = Join-Path $env:USERPROFILE ".ssh"
|
||||||
|
New-Item -ItemType Directory -Force -Path $sshDir | Out-Null
|
||||||
|
|
||||||
|
foreach ($f in @("id_rsa","id_rsa.pub","known_hosts")) {
|
||||||
|
$src = Join-Path $BackupPath $f
|
||||||
|
$dst = Join-Path $sshDir $f
|
||||||
|
if (Test-Path -LiteralPath $src) {
|
||||||
|
Copy-Item -LiteralPath $src -Destination $dst -Force
|
||||||
|
Write-Host "OK: restaurado $f"
|
||||||
|
} else {
|
||||||
|
Write-Warning "No existe en backup: $f"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repair-PrivateKeyAcl (Join-Path $sshDir "id_rsa")
|
||||||
|
Write-Host "OK: permisos ajustados id_rsa"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 5) Re-crear link de config (usa script del mismo folder)
|
||||||
|
$scriptLink = Join-Path $PSScriptRoot "New-SshConfigLink.ps1"
|
||||||
|
if (-not (Test-Path -LiteralPath $scriptLink)) {
|
||||||
|
throw "Falta New-SshConfigLink.ps1 en: $PSScriptRoot"
|
||||||
|
}
|
||||||
|
|
||||||
|
& $scriptLink -RepoConfig $RepoConfig
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Restauración lista. Abre PowerShell nuevo y prueba: ssh / Ctrl+R"
|
||||||
Loading…
Reference in new issue