CTRL + CがSSH接続を中断するのを防ぐ方法は?

CTRL + CがSSH接続を中断するのを防ぐ方法は?

停止したい場合は+をtail -f押してプロンプトに戻ります。しかし、接続のためにsshを実行すると、+は切断されます。 (国旗の意味の説明)CTRLCCTRLCここ)

ssh -t svf "cd ~/w/logs; tail -f some_file.log; exec $SHELL -l"

これ投稿では、リモートシェルが終了するのを防ぐ方法については説明していません。ssh -t remotehost command args ...

tail -fSSH接続を中断せずに+ stopコマンド(この場合)をどのように使用できますか?CTRLC

答え1

存在する

ssh -t svf "cd ~/w/logs; tail -f some_file.log; exec $SHELL -l"

-tローカルtty回線ルールがraw(パススルー)モードに設定され、擬似ttyがリモート側に作成されることを示します。

擬似端末にはデフォルト設定があります。これは、ほとんどのシステムでは、例えば1文字が^CSIGINTを疑似端末の前景プロセスグループに送信することを意味します。

ここではssh、コマンドを使用するときにsshd実行しますlogin-shell-of-the-remote-user -c that-command。これは非対話型シェルなので、ジョブ制御を実行しません。

具体的には、シェルは、実行するすべてのコマンドと同じプロセスグループ、つまり端末のフォアグラウンドプロセスグループで実行されます。

しかし、シェル$SHELL -l$SHELLおそらくあなたが望むものではないかもしれないローカルシステムで拡張されている)はインタラクティブシェルになります(呼び出しは行われず、-cstdinはターミナルデバイスなので)。したがって、別の場所にあります。プロセスグループ内のコマンド(パイプ)を実行し、必要に応じてそれを端末のフォアグラウンドプロセスにするかどうかを指定するプロセスグループ。

ここでは、SIGINTのみを受信したり、少なくともシェルではtail -fなくシャットダウンしたい場合は、リモートユーザーのログインシェルに応じていくつかのオプションがあります。

リモートユーザーのログインシェルがまたはのbash場合は、yash次のことができます。

ssh -t svf 'set -m; cd ~/w/logs && tail -f some_file.log; exec "$SHELL" -l'

この-mオプションを使用すると、ジョブ制御が可能になります。これは、シェルが別のプロセスグループ(対話型シェルなど)でパイプを実行するように指示します(通常は他のすべてのシェルではない)、前景で実行されているパイプのプロセスbashグループyashがパイプの前景プロセスグループになります。ターミナルデバイス(オンまたはSIGINTオフ^CなどSIGTSTP)、バックグラウンドで起動されたデバイスはそうではありません(したがってターミナルからの読み込みは禁止されます(SIGTTIN受信))。^Z

これにより、tail -fフォアグラウンドプロセスグループになる独自のプロセスグループで実行されます。tail実行中にCtrl + Cを入力すると、SIGINTのみがtail受信されます。

シェルがBourneに似ていることがわかっている場合は、別のオプションはSIGINTのハンドラを設定することです。

ssh -t svf 'trap : INT; cd ~/w/logs && tail -f some_file.log; exec "$SHELL" -l'

:ここでは、SIGINTを受信したときにコマンドを実行(ジョブなし)するようにシェルを設定します。子プロセスはハンドラを継承しますが、コマンドが実行されるとハンドラはデフォルト値にリセットされます(プロセス終了)。

したがって、実行中にCTRL-Cを押すと、tailシェルtailとテールの両方がSIGINTを受け取りますが、tailのみが終了し、シェルは実行を続けます"$SHELL" -l

リモートホスト(およびリモートシェルがBourneまたはcshに似ています)がそれを知っているかアクセスできる場合は、bash次のこともできます。yash

ssh -t svf 'cd ~/w/logs && bash -c "set -m; tail -f some_file.log"; exec "$SHELL" -l'

シェルを明示的に呼び出し、オプションをオンにbashして独自のフォアグラウンドプロセスグループから開始し、最初のソリューションのようにSIGINTのみを受け取るようにします-mtail

bash-4.3以上を使ってbash -c "set -m;に置き換えることができますbash -mc "。これは、インタプリタに渡された(-mand )オプションを無視する以前のバージョンでは機能しません-i( 。bash-c

答え2

CTRL+切断を防ぐためにはC対話型でなければなりません。

これはを通じて達成されますbash -i。だから私は実行できます:

ssh -t svf 'cd ~/w/logs; bash -i tail -f some_file.log; exec $SHELL -l'

しかし、この理由はそれ質問。この問題を解決するには、回避策を作成できます。コマンドを実行するためにリモートシステムにスクリプトを生成します(-i標識に注意してください。これは重要です。通常のログインと同じENVが必要な場合は、-lフラグを追加することもできます。

$ cat ~/cmd 
#!/bin/bash -i
cmd="$*"
eval $cmd

次に、コマンドを次のように修正しました。

ssh -t svf 'cd ~/w/logs; ~/cmd tail -f some_file.log; exec $SHELL -l'

今私は幸せで、CTRL+ Cwhenを実行できますtail -f。対話によりbash -iSSH接続が中断されず、exec $SHELL -lショートカットが呼び出された後にコマンドが実行されます。

重要なヒント:ローカルではなくリモート側で$ SHELLを拡張するには、「代わりに」を使用する必要があります。ありがとうございます。 Stéphane Chazelas

関連情報