この違いはなぜ重要なのでしょうか?以下のコードでは、2つのブロックの違いは最後の行です。
#!/bin/bash
if [[ -n "$1" ]]; then
sleep 1 &
p=$!
kill $p &> /dev/null
else
sleep 1 &
p=$!
kill $p &> /dev/null
/bin/true # This line is the sole difference.
fi
名前を指定するa.sh
と(私のLinuxコンピュータで)入手できます。
$ ./a.sh
/a.sh: line 16: 18103 Terminated sleep 1
$ ./a.sh foo
$ # no "Terminated" message
第二の出来事はなぜニュースがないのですか? Bashのデフォルト動作は「Termied」(この質問を見ました。)。
(p=$!
実際のコードではを使用していますが、上記の場合は使用できますkill $!
。)
編集する:セルゲイ・コロディアスネ問題に言及してください」真実はなぜそんなに偽ですか?(トピックから少し外れましたが読書に興味があります。) 残念ながら、このコメントに対応する回答が削除されたので、ここに記録します。ありがとうございます。 Sergiy。
ベストアンサー1
~によるとマテオイタリアの答え:
対照的に、killallを使用して同じ実験を実行すると、通常はすぐに「killed」メッセージが生成されます。時間/コンテキストスイッチ/外部コマンドを実行するために必要なすべては、制御がシェルに返される前にプロセスを終了するのに十分な長い遅延を引き起こします。
つまり、/bin/true
外部呼び出しによって引き起こされる遅延により、シェルがメッセージを印刷できるようになります。
また、/bin/echo
vsを使用してテストしましたecho
。
#!/bin/bash
if [[ -n "$1" ]]; then
sleep 1 &
p=$!
kill $p &> /dev/null
/bin/echo "a line"
else
sleep 1 &
p=$!
kill $p &> /dev/null
fi
次のスクリプトを使用してください。
$ bash ./mystery.sh
$ bash ./mystery.sh foo
a line
./mystery.sh: line 11: 10361 Terminated sleep 1
組み込みecho
:
$ bash ./mystery.sh
$ bash ./mystery.sh foo
a line
つまり、外部実行可能ファイルが呼び出されるという事実は、最後の子プロセスが返されたときにシェルに子プロセスとバックグラウンドジョブのチェックを実行することを強制します。次の場合:
if [[ -n "$1" ]]; then
sleep 1 &
p=$!
kill $p &> /dev/null
元のスクリプトでは、追加のコマンドは呼び出されず、最後の組み込みコマンドのみが呼び出されます。
これに加えて、いくつかのテストを実行しましたstrace
。
親プロセスが終了し、子プロセスを待っていないようです。つまり、シェルの親プロセスが早すぎます。明示的な検査を実行します。
$ strace -s 1024 -e kill bash mystery.sh
kill(9830, SIGTERM) = 0
mystery.sh: line 11: 9830 Terminated sleep 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=9830, si_uid=1000, si_status=SIGTERM, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
$ strace -s 1024 -e kill bash mystery.sh foo
kill(9839, SIGTERM) = 0
+++ exited with 0 +++
位置パラメータで追跡するときに待機呼び出しもないことに注意する価値があります。
$ strace -s 1024 -e kill,wait4 bash mystery.sh foo
kill(9910, SIGTERM) = 0
+++ exited with 0 +++
$ strace -s 1024 -e kill,wait4 bash mystery.sh
kill(9916, SIGTERM) = 0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=9916, si_uid=1000, si_status=SIGTERM, si_utime=0, si_stime=0} ---
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGTERM}], WNOHANG, NULL) = 9916
wait4(-1, 0x7ffe8e5bb110, WNOHANG, NULL) = -1 ECHILD (No child processes)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 9917
mystery.sh: line 11: 9916 Terminated sleep 1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=9917, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffe8e5bb250, WNOHANG, NULL) = -1 ECHILD (No child processes)
+++ exited with 0 +++