Führen Sie das Programm in der aktuellen Shell innerhalb des Shell-Skripts aus

Führen Sie das Programm in der aktuellen Shell innerhalb des Shell-Skripts aus

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 && zshoder Verwenden von evaloder 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 ipleer ist, aber aliasnicht 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
)"

verwandte Informationen