Hice un pequeño script de shell que analiza la configuración .ssh y me permite elegir una entrada con fzf y luego conectarme a ese host:
#!/bin/bash
set -o nounset -o errexit -o pipefail
list_remote_hosts()
{
choice="$(cat $HOME/.ssh/config | awk -v RS= -v FS=\\n -v IGNORECASE=1 '
{
ip = ""
alias = ""
id_file = ""
username = ""
port = ""
for (j = 1; j <= NF; ++j) {
split($j, tmp, " ")
if (tmp[1] == "Host") { alias = tmp[2] }
if (tmp[1] == "Hostname") { ip = tmp[2] }
if (tmp[1] == "IdentityFile") { id_file = tmp[2] }
if (tmp[1] == "User") { username = tmp[2] }
if (tmp[1] == "Port") { port = tmp[2] }
}
if (ip || alias && alias != "*") {
if (port == "")
{
port = "22"
}
print "ssh " username "@" ip " -i " id_file " -p " port
}
}
' | fzf)"
"$($choice)"
}
list_remote_hosts
Eso funciona, pero tengo problemas para otorgar propiedad al shell actual. Cuando se conecta, el script se congela (porque ssh se inicia en un subshell, me imagino). Una vez que escribo, por ejemplo, salir y el comando ssh finaliza, puedo ver el resultado.
Quiero otorgar automáticamente propiedad al shell actual cuando se ejecuta el script, para obtener el mismo comportamiento que ejecutar el comando ssh desde mi terminal.
Intenté todo tipo de cosas, como agregar && zsh
o usar eval
o exec
, pero ninguna funcionó. ¿Cómo puedo hacer esto?
Respuesta1
Intente cambiar "$($choice)"
a simplemente $choice
(sin comillas): eso debería expandir la salida de awk en palabras y generar el comando ssh del proceso actual.
Esto parece que podría ser un problema.
if (ip || alias && alias != "*") {
if (port == "") port = "22"
print "ssh " username "@" ip " -i " id_file " -p " port
}
¿Qué pasa si ip
está vacío pero alias
no lo está? Ingresarás al bloque, pero no usarás la variable alias en ninguna parte. Podrías querer
if (!ip) { ip = alias }
if (ip && ip != "*") { ...
Esto podría funcionar como una forma alternativa de estructurar la función. No probado:
remote_host_connect() {
awk '...' $HOME/.ssh/config \
| fzf \
| sh </dev/tty >/dev/tty 2>&1
}
Esto me funciona como un script independiente:
#!/bin/bash
eval "$(
awk -v RS= -F'[[:space:]]+' '{
for (i=1; i<NF; i+=2)
data[$i]=$(i+1)
ip = (data["HostName"] ? data["HostName"] : data["Host"])
if (ip && ip != "*")
printf "ssh %s@%s %s %s\n",
(data["User"] ? data["User"] : ENVIRON["LOGNAME"]),
ip,
(data["IdentityFile"] ? "-i " data["IdentityFile"] : ""),
"-p " (data["Port"] ? data["Port"] : 22)
}' ~/.ssh/config \
| fzf
)"