答え1
存在する
ssh -t svf "cd ~/w/logs; tail -f some_file.log; exec $SHELL -l"
-t
ローカルtty回線ルールがraw(パススルー)モードに設定され、擬似ttyがリモート側に作成されることを示します。
擬似端末にはデフォルト設定があります。これは、ほとんどのシステムでは、例えば1文字が^C
SIGINTを疑似端末の前景プロセスグループに送信することを意味します。
ここではssh
、コマンドを使用するときにsshd
実行しますlogin-shell-of-the-remote-user -c that-command
。これは非対話型シェルなので、ジョブ制御を実行しません。
具体的には、シェルは、実行するすべてのコマンドと同じプロセスグループ、つまり端末のフォアグラウンドプロセスグループで実行されます。
しかし、シェル$SHELL -l
($SHELL
おそらくあなたが望むものではないかもしれないローカルシステムで拡張されている)はインタラクティブシェルになります(呼び出しは行われず、-c
stdinはターミナルデバイスなので)。したがって、別の場所にあります。プロセスグループ内のコマンド(パイプ)を実行し、必要に応じてそれを端末のフォアグラウンドプロセスにするかどうかを指定するプロセスグループ。
ここでは、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のみを受け取るようにします-m
。tail
bash-4.3
以上を使ってbash -c "set -m;
に置き換えることができますbash -mc "
。これは、インタプリタに渡された(-m
and )オプションを無視する以前のバージョンでは機能しません-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 -i
SSH接続が中断されず、exec $SHELL -l
ショートカットが呼び出された後にコマンドが実行されます。
重要なヒント:ローカルではなくリモート側で$ SHELLを拡張するには、「代わりに」を使用する必要があります。ありがとうございます。 Stéphane Chazelas