プロセスを終了して待ってから、プロセスが完了するまで生成するために生成したいbashスクリプトの操作ソリューションを見つけて見つけましたが、見つかりませんでした。私はまだLinuxについて多くを学んでいます。
コンテキスト: プロセス FOO が実行中です。プロセスBARはFOOを確認して終了するために使用されます(これら2つのプロセスの内部を制御することはできません)。私ができることは、BARにコマンドを渡して実行することだけです。
この例では、FOO を終了するコマンドを BAR に送信します。これにより、別のプロセスが作成され、バックグラウンドに配置されます。
ターゲット:20個のFOOに対して(BARを介して)シャットダウンを実行し、スクリプトの次の部分を続行する前に、すべてのFOOが死ぬのを待つために20個のコマンドを同時に実行しようとしています。
質問:これまでにできることは、BARが実行されるのを待ってからバックグラウンドプロセスがFOOを終了する前に続けることです。
BAR exit FOO1
BAR exit FOO2
...
BAR exit FOO20
wait
do more stuff
私も試しました
BAR exit FOO1
PID1=$!
BAR exit FOO2
PID2=$!
wait $PID1 $PID2
不運。
答え1
待機中の他のプロセスがない場合は、wait
引数なしですべてのバックグラウンド操作が完了するまで待ちます。私はしばしば次のような構造を使用します。
for i in *; do md5sum $i & done
wait
ただし、スクリプトに別のバックグラウンド操作があると中断されますが、サブシェルにラップすることはできます。
(for i in *; do md5sum $i & done; wait) & all_md5sum=$!
...
wait $all_md5sum
答え2
FOO1
まず、2つのプロセスのみを使用し、次FOO2
のスクリプトで実行したい場合など、より簡単なシナリオを試してみてくださいparent.sh
。
#!/bin/bash
FOO1 &
pid1=$!
echo "Child PID=$pid1 launched"
FOO2 &
pid2=$!
echo "Child PID=$pid2 launched"
BAR exit FOO1
BAR exit FOO2
echo "Pausing to wait for children to finish..."
wait $pid1
wait $pid2
echo "Children finished, moving on."
これが2FOO
秒間動作していることを確認し、その場合は20秒間動作していることを確認してください。
説明する
FOO
私たちは内部とプロセスを見ることができないので、あなたが投稿したBAR
ものにのみ依存しており、あなたが言ったことを理解しています
- 「プロセスBARはFOOを確認して終了するために使用されます。」
- つまり、クリップを公開する前に、ある時点で
FOO1
特定の方法で開始してBAR exit FOO1
クリップに影響を与えます。
もともと投稿したスニペットでは、次のように作成しました。
BAR exit FOO1
PID1=$!
$!
最近のバックグラウンドプロセスのキャプチャ- しかし、
BAR exit FOO1
これはバックグラウンドに入るプロセスではありません。あなたが言ったように、BARを使用してFOOを制御する手段です。 「BARはFOOを確認して殺すために使用されます。」 - したがって、PIDを
$!
キャプチャする可能性はほとんどありません。FOO1
したがって、FOO
*プロセスが実際に開始されるpidをキャプチャする必要があります。たとえば、オールインを実行していてparent.sh
プロセスが2つしかない場合は、次のようにします。
#!/bin/sh
FOO1 &
pid1=$!
echo "Child PID=$pid1 launched"
FOO2 &
pid2=$!
echo "Child PID=$pid2 launched"
- Lowercase
pid1
、一貫性がある限り、元の大文字を使用することもできます。私は、誤った使用環境変数と区別するための慣例として小文字を使用することを好みます。 #
echoは何が起こっているのかを知るために追跡するためのオプションです。
次に、確認して終了するように要求したコマンドを実行しますFOO1
。FOO2
BAR exit FOO1
BAR exit FOO2
次に、
echo "Pausing to wait for children to finish..."
wait $pid1
wait $pid2
echo "Children finished, moving on."
- 繰り返しますが、
echo
sはオプションですが、問題を解決しながら情報を提供し、何が起こっているのかを伝えます。 wait
みんなのために$pid
...- 以下は、ingが終わった
echo
ことを知らせる別のオプションです。wait
クレジット取引
2009年撮影無料PDF 506ページの非同期スクリプトの例
答え3
各コマンドのファイルをタッチしてファイルを確認できます。簡単な例は次のとおりです。
#!/usr/local/bin/bash
# Flag to knkow when completed
finished=0;
# The commands t run
declare -a commands=('cmd1' 'cmd2' 'cmd3' 'cmd4');
# Fork all commands
for cmd in "${commands[@]}"; do
./$cmd &
done
# Loop to wait for all processes to finish
loop=0;
while [ $finished -eq 0 ]; do
# Just for visual effect
loop=$((loop+1));
echo "Loop $loop";
sleep 1;
files=0;
for cmd in "${commands[@]}"; do
# Each program shoudl touch a file so that we
# can know it has completed successfully
if [ -e ".$cmd" ]; then
echo "Process $cmd completed";
files=$((files+1));
else
# No need to continue if anything is not done
# Error checking here like a TTL value or ps -ef | grep pid etc
echo "Waiting for process $cmd";
break;
fi;
done
# if we have as many files as executed commands
if [ "$files" -eq ${#commands[@]} ]; then
finished=1;
fi
done;
echo 'All jobs completed successfully';
# Clean up after yourself
for cmd in "${commands[@]}"; do
rm -f ".$cmd";
done;
次に、各cmd1、cmd2 ... cmdNをテストするには、次のようにします。
#!/usr/local/bin/bash
num=1;
echo "Enter cmd$num";
sleep 1; # use different sleep values to simulate execution
touch ".cmd$num"
echo "Exit cmd$num";
答え4
$ PID1が実行されている場合はtrueと評価されます。 if [kill -s 0 $PID1 ]
if句を複数持つことができます。 PID が実行されていない場合は false と評価されます。この節(他の節と共に)は、必要に応じてスクリプトの流れを制御する必要があります。