プロセスを終了した後、bashが「いつもそうではありません」が「終了しました」というメッセージを表示するのはなぜですか? [コピー]

プロセスを終了した後、bashが「いつもそうではありません」が「終了しました」というメッセージを表示するのはなぜですか? [コピー]

この違いはなぜ重要なのでしょうか?以下のコードでは、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/echovsを使用してテストしました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 +++

おすすめ記事