Bashについて2つの質問があります。
(Q1)長期実行コマンド(C1)を使用して、いくつかの出力を生成する長期実行コマンド(C1)をシミュレートし、処理をシミュレートするために使用されるコマンド(C2)を考慮する仮想コマンドラインtail -f SomeFile | wc
C1が終了すると出力されます。長い時間(通常より長い時間)を待ってから、これまでにどの出力が生成されたかを確認したいので、C1を終了させたいと思います。ただし、Ctrl-Cを押すとパイプライン全体が終了します。tail
wc
C1(または独自の複合コマンドの場合は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)
cmd1
Control-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$