
ProxyCommand が使用されている場合、OpenSSH_8.4p1 は同じ接続を共有する他のセッションを終了するのはなぜですか? これを防ぐ方法はありますか?
注: ProxyCommand 引数が省略されている場合、この動作は発生しないようです。
再現する手順:
- ローカルホストへの既存の共有接続をすべて切断します。
ssh -o ControlPath=/tmp/%C -O exit 127.0.0.1 2>/dev/null
ssh -o ControlPath=/tmp/%C -O exit localhost 2>/dev/null
- 次のコマンドをそれぞれ異なるターミナルで 2 回並行して実行します。
ssh -F none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o ControlMaster=auto -o ControlPath=/tmp/%C -o ControlPersist=1d \
-o ProxyCommand='ssh -W %h:%p 127.0.0.1' \
localhost 'sleep 3600'
- Ctrl + C と入力して、SIGINT で最初の ssh プロセスを中断します。
予想される行動
- SIGINT されたプロセスのみが終了します。
- 他のプロセスは影響を受けずに実行され続けます。
実際の行動
- 両方のプロセスが終了します。
答え1
SIGINT されたプロセスのみが終了します。
「プロセス」は誤った前提です。Ctrl+C SIGINT
フォアグラウンドプロセスに送信するグループターミナルのプロセス グループには複数のプロセスが含まれる場合があります。
次に、これが関連します。
ProxyCommand
サーバーに接続するために使用するコマンドを指定します。コマンド文字列は行末まで拡張され、exec
シェル プロセスが長引かないようにユーザーのシェル ディレクティブを使用して実行されます。
[…]
(ソース)
コマンドは、 main と同じプロセス グループ内でローカルに実行されますssh
。この例ではコマンドは ですssh …
が、一般的には何でもかまいません。いずれにしても、コマンドは を認識せずControlMaster
、ControlPersist
main に使用しますssh
。
Ctrl+を押すとC、フォアグラウンドプロセスグループの各プロセスが を取得します。以外の場合、このソケットは最初から によって処理されるため、 SIGINT
"main"ssh
は のソケットに影響を与えずに終了します。ControlPath
ControlPersist
no
さらにもう一つ ssh
意図的に独自のプロセス グループ内に生成されたプロセスは存続できます。このコンテキストでは、これを真のメインと呼ぶことができますssh
。
予期しない動作は、 で指定されたコマンドがProxyCommand
フォアグラウンド プロセス グループで生成され、中断する とSIGINT
連携して動作するためです。 コマンドは、通常どおりにシグナルに反応します。 この場合、コマンドは で終了します。 また、 コマンドはすべてのデータを中継することになっていたため、マスター接続 (実際にメインとなる) は役に立たなくなりました。 依存するすべてのプロセスとともに終了します。ssh
SIGINT
ssh
ssh
したがって、オリジナルでは、マスター接続 (およびソケット) の処理がssh
確実に維持されるように追加の作業が行われますが、同様に重要な で指定されたコマンドに対してはこれが実行されません。これはバグと呼べると思います。ssh
CtrlCProxyCommand
で指定されたコマンドが、でProxyCommand
免疫によって生成されたほうが良いでしょう。ssh
そのCtrlプロセス グループ。私はこれを十分に分析していません。とにかく、今のところはそうではありません。コマンドは、 +を押した時点でフォアグラウンド プロセス グループであるプロセス グループで生成さCれるため、 になりますSIGINT
。
回避策としては、コマンドを の影響を受けないようにすることですSIGINT
。 内部ではが自動的にを使用するため、 を直接ProxyCommand
使用することはできません。これは意味をなさず、動作しません。さらに別のシェルが必要です。trap
ProxyCommand
exec
exec trap …
ssh -F none -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-o ControlMaster=auto -o ControlPath=/tmp/%C -o ControlPersist=1d \
-o ProxyCommand='sh -c "trap \"\" INT; exec ssh -W %h:%p 127.0.0.1"' \
localhost 'sleep 3600'
私のテストでは、免疫があっても、時間が来たときにSIGINT
この内部ssh
が終了するのを防ぐことはできず、有限設定のためマスター接続が終了するはずであることが示されていますControlPersist
。