[編集:これは、生成されたすべてのプロセスを終了する方法を尋ねる他の質問と似ています。答えはすべてpkillを使用しているようです。だから私の質問の中核はおそらく:スクリプトによって生成されたすべてのプロセスにCtrl-C / Zを伝播する方法はありますか? ]
coreutilsのコマンドを使用してSoXを呼び出す場合(議論rec
)timeout
ここ)、Bashスクリプトから呼び出されると、キーストロークでそれを終了する方法がないようです。
例:
timeout 10 rec test.wav
Ctrl... bashで+CまたはCtrl+を使用して終了できますが、Zスクリプト内で呼び出すときはそうではありません。
timeout 10 ping nowhere
Ctrl... bashで+CまたはCtrl+で終了することができますZ。 +はスクリプト内で実行されるときですCtrl。Z
プロセスIDを見つけて終了できますが、標準の割り込みキーを押すことができないのはなぜですか?私のスクリプトを設定する方法はありますか?
ベストアンサー1
Ctrl+シグナルキーがCフォアグラウンドのすべてのプロセスにシグナルを送信するのを待ちます。プロセスグループ。
通常、プロセスグループはパイプです。たとえば、head <somefile | sort
実行中のプロセスhead
と実行中のプロセスはsort
シェルと同じプロセスグループにあるため、両方がシグナルを受け取ります。somecommand &
バックグラウンドでジョブを実行している場合()ジョブは独自のプロセスグループにあるため、Ctrl+を押してもC影響を受けません。
プログラムtimeout
は自分自身を独自のプロセスグループに配置します。ソースコードから:
/* Ensure we're in our own group so all subprocesses can be killed.
Note we don't just put the child in a separate group as
then we would need to worry about foreground and background groups
and propagating signals between them. */
setpgid (0, 0);
タイムアウトが発生した場合は、timeout
そのグループが属するプロセスグループを終了する簡単な回避策を実行してください。自分を別のプロセスグループに入れたので、親プロセスはそのグループに属しません。ここでプロセスグループを使用すると、サブアプリケーションが複数のプロセスに分岐した場合、すべてのプロセスがシグナルを受け取ります。
timeout
コマンドラインから直接実行して+を押すと、子CtrlプロセスはC結果SIGINTを受け取りますが、親の対話型シェルはそうではありません。スクリプトから呼び出されると、スクリプトを実行しているシェルだけがシグナルを受け取ります。別のプロセスグループにあるため、信号を受信しません。timeout
timeout
timeout
timeout
組み込み関数を使用して、シェルスクリプトでシグナルハンドラを設定できますtrap
。残念ながら、それほど単純ではありません。考えてみてください:
#!/bin/sh
trap 'echo Interrupted at $(date)' INT
date
timeout 5 sleep 10
date
Ctrl2秒後に+を押すと、Cまだ5秒待ってから「Interrupted」メッセージが表示されます。これは、バックグラウンドジョブがアクティブな間にシェルがトラップコードを実行しないためです。
この問題を解決するには、バックグラウンドでタスクを実行してください。シグナルハンドラでは、kill
シグナルをtimeout
プロセスグループに転送するための呼び出しが行われます。
#!/bin/sh
trap 'kill -INT -$pid' INT
timeout 5 sleep 10 &
pid=$!
wait $pid