シェルスクリプト内の現在のシェルでプログラムを実行する

シェルスクリプト内の現在のシェルでプログラムを実行する

私は、.ssh 構成を解析し、fzf でエントリを選択してそのホストに接続できるようにする小さなシェル スクリプトを作成しました。

#!/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

それは動作しますが、現在のシェルに所有権を与える際に問題が発生します。接続すると、スクリプトがフリーズします (ssh がサブシェルで起動されるためだと思います)。たとえば exit と入力して ssh コマンドを終了すると、出力が表示されます。

スクリプトの実行時に現在のシェルに所有権を自動的に付与して、ターミナル内から ssh コマンドを実行するのと同じ動作が得られるようにしたいと考えています。

&& zsh追加や の使用evalなど、さまざまなことを試しましたがexec、どれも機能しませんでした。どうすればいいでしょうか?

答え1

"$($choice)"単純に(引用符なし)に変更してみてください$choice。これにより、awkの出力が単語に展開され、現在のプロセスからsshコマンドが生成されます。


これは問題になりそうだ

if (ip || alias && alias != "*") {
    if (port == "") port = "22"
    print "ssh " username "@" ip " -i " id_file " -p " port
}

ipが空でない場合はどうなるでしょうaliasか?ブロックに入りますが、エイリアス変数はどこにも使用しません。

if (!ip) { ip = alias }
if (ip && ip != "*") { ...

これは関数を構造化する別の方法として機能する可能性があります。未テスト:

remote_host_connect() {
    awk '...' $HOME/.ssh/config \
    | fzf \
    | sh </dev/tty >/dev/tty 2>&1
}

これはスタンドアロン スクリプトとして機能します。

#!/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
)"

関連情報