Bash 4.3ではうまく動作するスクリプトがありますが、Bash 3.2では予期しない動作が発生します。簡略化されたバージョンは次のとおりです。
set -o errexit -o pipefail
task() {
local name=${1}
local duration=${2}
trap 'echo "[${SECONDS} secs] ${name}: SIGINT"; exit 255' INT
echo "[${SECONDS} secs] ${name}: Running"
sleep "${duration}"
echo "[${SECONDS} secs] ${name}: Done"
}
trap 'echo "[${SECONDS} secs] SIGINT"; exit 255' INT
task 'Task 1' 5 &
task 'Task 2' 5 &
wait
echo "[${SECONDS} secs] Done"
以下は、bash 4.3(4.3.42(1)-release)を使用してCTRL-Cを2秒間実行した後の出力です。
[0 secs] Task 1: Running
[0 secs] Task 2: Running
^C[2 secs] SIGINT
[2 secs] Task 2: SIGINT
[2 secs] Task 1: SIGINT
prompt>
同じですが、bash 3.2(3.2.57(1) - リリース)の場合:
[0 secs] Task 1: Running
[0 secs] Task 2: Running
^C[2 secs] SIGINT
prompt> [5 secs] Task 2: Done
[5 secs] Task 1: Done
bash 3.2で上記のスクリプトが正しく機能しないという既知の問題はありますか?回避策がありますか?
私が試したいくつかのことは次のとおりです。
親エントリにはシグナルハンドラはありません。
# bash 4.3 [0 secs] Task 1: Running [0 secs] Task 2: Running ^C[2 secs] Task 2: SIGINT [2 secs] Task 1: SIGINT prompt> # bash 3.2 [0 secs] Task 1: Running [0 secs] Task 2: Running ^C prompt> [5 secs] Task 2: Done [5 secs] Task 1: Done
信号ハンドラはまったくありません。
# bash 4.3 [0 secs] Task 1: Running [0 secs] Task 2: Running ^C prompt> # bash 3.2 [0 secs] Task 1: Running [0 secs] Task 2: Running ^C prompt> [5 secs] Task 2: Done [5 secs] Task 1: Done
親のシグナルハンドラはSIGINT()を使用してプロセスグループを終了します
kill -INT -- -$$
。[0 secs] Task 1: Running [0 secs] Task 2: Running ^C[2 secs] SIGINT [2 secs] Task 2: SIGINT [2 secs] Task 1: SIGINT prompt> [0 secs] Task 1: Running [0 secs] Task 2: Running ^C[2 secs] SIGINT prompt> [5 secs] Task 2: Done [5 secs] Task 1: Done
親のシグナルハンドラは、SIGTERM(SIGTERMをキャプチャするアクション)を使用してプロセスグループを終了します。
# bash 4.3 [0 secs] Task 1: Running [0 secs] Task 2: Running ^C[2 secs] SIGINT [2] 92813 terminated bash minimal_example.sh prompt> # bash 3.2 [0 secs] Task 1: Running [0 secs] Task 2: Running ^C[2 secs] SIGINT Terminated: 15 Terminated: 15 [2 secs] Task 2: SIGTERM [2 secs] Task 1: SIGTERM [1] 92836 terminated /bin/bash minimal_example.sh prompt>
最後は3.2で正常に動作するのに最も近いです。しかし、4.3では、同じコードが異なる動作をします。
答え1
ユーザーは、多くのbash
場合、make
ユーザーに影響を与える既知の問題の被害者である可能性があります。
Bash 4をチェックしていませんが、bash 3
スクリプト内でジョブ制御が誤って実行されています。これにより、^C
コマンドが対話型でなくても、子プロセスが別々のプロセスグループで実行されるため、簡単に終了しない複数のサブディレクトリループを含むメイクファイルが生成されることがよくあります。
smake
回避策を含め/bin/sh
、bash
SIGINTを現在実行中のコマンドのプロセスグループに明示的に渡します。ただし、これは使用されますC
。
サブプロセスグループを取得する標準のUNIXコマンドがないため、スクリプトの一般的なシェルを使用して同じ機能を実行することはできません。