現在のプロセスのみを終了してシェルパイプラインを続行するにはどうすればよいですか?

現在のプロセスのみを終了してシェルパイプラインを続行するにはどうすればよいですか?

Bashについて2つの質問があります。

(Q1)長期実行コマンド(C1)を使用して、いくつかの出力を生成する長期実行コマンド(C1)をシミュレートし、処理をシミュレートするために使用されるコマンド(C2)を考慮する仮想コマンドラインtail -f SomeFile | wcC1が終了すると出力されます。長い時間(通常より長い時間)を待ってから、これまでにどの出力が生成されたかを確認したいので、C1を終了させたいと思います。ただし、Ctrl-Cを押すとパイプライン全体が終了します。tailwcC1(または独自の複合コマンドの場合はC1のコンポーネント)のみを終了するにはどうすればよいですか?
C1が多くのファイルを繰り返していくつかのテキストをgrepしますが、1つのファイルが停止しているいくつかのnfsサーバーから来た場合は、grepプロセスを終了したいと思います。

(for F in A B C D E ; do grep sometext $F ; done) | wc

ここで、Ctrl-Cはコマンドライン全体を終了しますが、現在実行中(または停止中)のプロセスのみを終了し、残りのファイル処理を続けたいと思います。

私が持っている1つの解決策は、新しい接続を開き、ps出力を取得してから「終了」することでした。現在のプロセスだけを終了する奇妙なキーの組み合わせなど、Bash自体にソリューションがあるかどうか疑問に思います。

(Q2)この質問の例を挙げて、次のコマンドラインを作成しました。ここでCtrl-Cを押すと、次のような追加の出力行が表示されます。

# echo `ping 127.0.0.1` | wc
^C

#

逆引用符( ``)を使用しないと、追加の行は表示されません。

# tail -f SomeFile | wc
^C
#

バックティック( ``)はbash自体によって処理され、子プロセスが終了した場合はまだ「空の出力」と見なされ、追加の行で印刷されると思いますか?

答え1

その後、bash次を実行できます。

cmd1 | cmd2 | (trap '' INT; cmd3)

cmd1Control-Cは終了しますcmd2が、終了しませんcmd3

例:

$ while sleep .1; do echo -n 1; done | (trap '' INT; tr 1 2)
^C222222222
$ while sleep .1; do echo -n 1; done | tr 1 2
^C

これは、「無視」信号処理が子プロセスによって継承されるという事実を利用します。これはコマンドtrap '' INTにも影響します。trしかし、もちろん、いくつかのコマンドは独自のハンドラをSIGINTインストールするので、これらの仮定は壊れます。

ksh93残念ながら、愚かな間違いのために動作しません。解決策は次のとおりです。

ksh93$ while sleep .1; do echo -n 1; done | sh -c 'trap "" INT; exec tr 1 2'
^C222222222ksh93$

答え2

このコマンドは、stty -aすべてのキーボードショートカットを表示します。マッピングされた信号は、Ctrl-C(SIGINT)、Ctrl-\(SIGQUIT)、およびCtrl-Z(SIGSUSP)のみです。他の信号へのバインディングはありません。

私はあなたが明示した解決策を使用します。つまり、シャットダウンする必要がある別のシェル、ps出力、およびプロセスです。kill

2番目の質問では、アクセント( ``)のためではなく、echo次の例を試してください。

# echo `sleep 10` | wc
^C

# `sleep 10` | wc
^C
# sleep `echo "10"` | wc
^C
#

答え3

次のコマンドを使用してテストすると、うまく動作します。

tail -f /var/log/kern.log & read -t 10 ;kill $!

上記のコマンドは10秒間実行された後に終了します。

関連情報