8

環境:

ユーザーは、実行するカスタム スクリプトを提供してくれます。これらのスクリプトは、複数の GUI プログラムやバックエンド サービスを開始するためのスクリプトなど、どのようなものでもかまいません。スクリプトの作成方法を制御することはできません。これらのスクリプトはブロッキング タイプにすることができます。つまり、実行はすべての子プロセス (順次実行されるプログラム) が終了するまで待機します。

#exaple of blocking script
echo "START"
first_program 
second_program 
echo "DONE"

またはノンブロッキングタイプ、つまり、子プロセスをバックグラウンドで fork し、次のようなものを終了するタイプ

#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"

私は何を達成しようとしていますか?

ユーザー提供のスクリプトは、上記の 2 つのタイプのいずれか、または両方の組み合わせにすることができます。私の仕事は、スクリプトを実行し、スクリプトによって開始されたすべてのプロセスが終了するまで待ってから、ノードをシャットダウンすることです。ブロッキングタイプの場合、ケースは単純です。つまり、スクリプト実行プロセスの PID を取得し、ps -ef|grep -ef PID のエントリがなくなるまで待ちます。ノンブロッキング スクリプトが問題を引き起こしている

スクリプトの実行によって生成されたすべての子プロセスの PID のリストを取得する方法はありますか? ポインタやヒントは高く評価されます

4

5 に答える 5

7

ps --ppid $PIDプロセスのすべての子プロセスをリストします$PID

于 2013-09-06T17:27:40.720 に答える
7

waitによって開始されたすべてのバックグラウンド プロセスが完了するまで待機するために使用できますuserscript。現在のシェルの子でのみ機能するためwait、別のプロセスとして実行するのではなく、スクリプトをソースする必要があります。

( source userscript; wait )

明示的なサブシェルでスクリプトを取得すると、新しいプロセスの開始を十分にシミュレートする必要があります。そうでない場合は、サブシェルをバックグラウンドで実行することもできます。これにより、新しいプロセスが強制的に開始され、完了するまで待機ます。

( source userscript; wait ) & wait
于 2013-09-06T18:08:27.603 に答える
5

他のプロセスによって継承されるファイル記述子を開き、使用されなくなるまで待つことができます。これは、必要に応じてプロセスが回避することは可能ですが、通常は問題なく機能する低オーバーヘッドの方法です。

 foo=$(mktemp)
 ( flock -x 5000; theirscript; ) 5000> "$foo"
 flock -x 0 < "$foo"
 rm "$foo"
 echo "The script and its subprocesses are done"

などの ptrace を使用して、呼び出されたすべてのプロセスをたどることができますstrace。これは簡単ですが、関連するオーバーヘッドがあり、スクリプトが suid バイナリを呼び出すと機能しない場合があります。

strace -f -e none theirscript
于 2013-09-06T17:42:00.780 に答える
1

pgrep -P <parent_pid>子プロセスのリストを取得するために使用できます。例:

IFS=$'\n' read -ra CHILD_PROCS -d '' < <(exec pgrep -P "$1")

孫を取得するには、各子プロセスで同じ手順を実行するだけです。

私のブログBash functions をチェックして、プロセスツリーを一覧表示して強制終了したり、シグナルを送信したりしてください。

これらの関数の 1 つを使用して、1 つのプロセスの下で生成されたすべてのプロセスを適切に一覧表示できます。それぞれに、処理するシグナルを送信する独自​​の方法または順序があります。

それらによる唯一の制限は、プロセスがまだ接続されている必要があり、孤立していないことです。何らかの方法でプロセスをグループ化する方法を見つけることができれば、それが解決策になる可能性があります。

于 2013-09-06T17:52:31.867 に答える
1

聞かれた質問に簡単に答える。呼び出している各スクリプトのプロセス ID を同じ変数に格納できます。

echo "START"
first_program &
child_process_ids+="$! "
second_program &
child_process_ids+="$! "
echo $child_process_ids
echo "DONE"

$child_process_ids は、スペースで区切られたプロセス ID の文字列です。さて、これは尋ねられた質問に答えますが、私がすることは少し異なります. 各スクリプトを for ループから呼び出し、そのプロセス ID を保存してから、別の for ループで各スクリプトが終了するのを待ち、各終了コードを個別に検査します。同じ例を使用すると、次のようになります。

echo "START"

scripts="first_program second_program"

for script in $scripts; do
    #Call script and send to background
    ./$script &

    #Store the script's processID that was just sent to the background
    child_process_ids+="$! "
done

for child_process_id in $child_process_ids; do

    #Pass each processId into the wait command to retrieve its exit 
    #code and store it in $rc
    wait $child_process_id
    rc=$?

    #Inspect each processes exit code
    if [ $rc -ne 0 ]; then
        echo "$child_process_id failed with an exit code of $rc"
    else
        echo "$child_process_id was successful"
    fi
done
于 2016-11-07T22:15:57.233 に答える