SSHポートフォワーディング
便利ですね。普通はこんな具合にssh
コマンドを立ち上げっぱなしにすると思います。
$ ssh www.example.com -fNL 8000:localhost:8000 # -Lでポート指定、-fNでバックグラウンド待機
$ mycommand foo bar # ポートフォワーディングが必要なコマンドを実行する
mycommandの出力:fooをbarするにゃん
$ mycommand hoge fuga # SSH起動中はポートフォワーディングが持続する
mycommandの出力:hogeをfugaするにゃん
...
さて、特定のコマンドを実行する間だけポートフォワーディングしたいとします。ナイーブにやるならこうなりますね。
$ ssh www.example.com -NL 8000:localhost:8000 &
[1] 4273
$ mycommand foo bar
mycommandの出力:fooをbarするにゃん
$ kill 4273
[1]+ Done ssh www.example.com -NL 8000:localhost:8000 &
これではタイプしている間に宇宙が熱的死を迎えてしまいます。
まずは関数化
とりあえず面倒な部分を設定ファイルにまとめます。
~/.ssh/config
Host myhost
HostName www.example.com
LocalForward 8000 localhost:8000
~/.bash_profile
function spf() {
ssh $1 -N & # $1はサーバ名
local pid=$! # SSHのプロセスIDを保存する
shift # $2以降はコマンドとその引数
$@ # コマンドを呼び出す
kill $pid # SSHポートフォワーディングを止める
}
これでssh
でリモートのコマンドを実行するようなノリで使えるようになりました。
$ spf myhost mycommand foo bar
[1] 42365
mycommandの出力:fooをbarするにゃん
[1]+ Done ssh myhost -N &
コマンドの出力の前後に余計なメッセージが出ちゃいますねえ。ぐんにょり。
余計なメッセージを消す
コマンドの前後のメッセージは、バックグラウンドジョブの起動と終了のメッセージです。これらを非表示にする処理を追加すれば…
~/.bash_profile
function spf() {
set +m # バックグラウンドジョブの終了メッセージを非表示にする
{ ssh $1 -N & } 2> /dev/null # バックグラウンドジョブの起動メッセージを消す
local pid=$! # SSHのプロセスIDを保存する
shift # $2以降はコマンドとその引数
$@ # コマンドを呼び出す
kill $pid # SSHポートフォワーディングを止める
sleep 0.01 # ジョブ終了メッセージが出ないように少し待ってから
set -m # 終了メッセージの表示設定をもとに戻す
}
🏆🏆🏆 優 勝 🏆🏆🏆
$ spf myhost mycommand foo bar
mycommandの出力:fooをbarするにゃん
ポートフォワーディングを意識せず使う
もしSSH接続先が1つに決まっているならば、エイリアスを設定すると…
~/.bash_profile
alias mycommand='spf myhost mycommand'
🏰🏰🏰 殿 堂 入 り 🏰🏰🏰
$ mycommand foo bar
mycommandの出力:fooをbarするにゃん
ポートフォワーディングを意識する必要もなくなりましたとさ。
謝辞
バックグラウンドジョブの起動メッセージを消す方法は、ひよどりBasistさんに教えていただきました。ありがとうございます。
{ sleep 100 & } 2> /dev/null
— ひよどりBasist (@VisualBasist) April 22, 2021
ちょっと違うかも