.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がサブシェルで起動されたようです)。たとえば、終了を入力し、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
)"