Ich habe ein kleines Shell-Skript erstellt, das die SSH-Konfiguration analysiert und mir ermöglicht, mit fzf einen Eintrag auszuwählen und dann eine Verbindung zu diesem Host herzustellen:
#!/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
Das funktioniert, aber ich habe Probleme, der aktuellen Shell den Besitz zuzuweisen. Wenn eine Verbindung hergestellt wird, friert das Skript ein (weil ssh vermutlich in einer Subshell gestartet wird). Sobald ich z. B. exit eingebe und der ssh-Befehl beendet wird, kann ich die Ausgabe sehen.
Ich möchte den Besitz automatisch an die aktuelle Shell übertragen, wenn das Skript ausgeführt wird, sodass dasselbe Verhalten erzielt wird, als wenn ich den SSH-Befehl von meinem Terminal aus ausführe.
Ich habe alles Mögliche versucht, z. B. Anhängen && zsh
oder Verwenden von eval
oder exec
, aber nichts davon hat funktioniert. Wie kann ich das machen?
Antwort1
Versuchen Sie, "$($choice)"
es einfach zu ändern $choice
(ohne Anführungszeichen). Dadurch sollte die awk-Ausgabe in Wörter umgewandelt und der SSH-Befehl vom aktuellen Prozess aus aufgerufen werden.
Das scheint ein Problem zu sein
if (ip || alias && alias != "*") {
if (port == "") port = "22"
print "ssh " username "@" ip " -i " id_file " -p " port
}
Was passiert, wenn ip
leer ist, aber alias
nicht ist? Sie betreten den Block, verwenden aber die Aliasvariable nirgendwo. Vielleicht möchten Sie
if (!ip) { ip = alias }
if (ip && ip != "*") { ...
Dies könnte als alternative Möglichkeit zur Strukturierung der Funktion funktionieren. Ungetestet:
remote_host_connect() {
awk '...' $HOME/.ssh/config \
| fzf \
| sh </dev/tty >/dev/tty 2>&1
}
Das hier funktioniert bei mir als eigenständiges Skript:
#!/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
)"