Bash コマンドを実行する必要があります。ただし、このコマンドの実行には数分かかります。
このコマンドを正常に (同期的に) 実行すると、コマンドの実行が完了するまでアプリケーションがハングします。
Perl スクリプトから非同期で Bash コマンドを実行するにはどうすればよいですか?
Bash コマンドを実行する必要があります。ただし、このコマンドの実行には数分かかります。
このコマンドを正常に (同期的に) 実行すると、コマンドの実行が完了するまでアプリケーションがハングします。
Perl スクリプトから非同期で Bash コマンドを実行するにはどうすればよいですか?
これを行う通常の方法は、fork
. exec
スクリプト フォークを作成すると、子は Bash スクリプトでまたはを呼び出しますsystem
(子が Bash スクリプトのリターン コードを処理する必要があるか、それ以外の方法で対話する必要があるかによって異なります)。
次に、親はおそらくwait
and/orSIGCHILD
ハンドラーの組み合わせを必要とするでしょう。
それを処理する方法の正確な詳細は、状況と正確なニーズに大きく依存します.
結果を気にしない場合は、そのまま使用できますsystem("my_bash_script &");
。すぐに戻り、スクリプトは必要な処理を実行します。
私は2つのファイルを持っています:
$ cat wait.sh
#!/usr/bin/bash
for i in {1..5}; { echo "wait#$i"; sleep 1;}
$cat wait.pl
#!/usr/bin/perl
use strict; use warnings;
my $t = time;
system("./wait.sh");
my $t1 = time;
print $t1 - $t, "\n";
system("./wait.sh &");
print time - $t1, "\n";
出力:
wait#1
wait#2
wait#3
wait#4
wait#5
5
0
wait#1
wait#2
wait#3
wait#4
wait#5
2 番目の呼び出しがすぐに返されることがわかりますが、stdout への書き込みが続けられます。
子供と通信する必要がある場合は、and (and ) を使用fork
してリダイレクトする必要があります。または、IPC::Open2またはIPC::Open3パッケージを使用できます。とにかく、呼び出し元が終了する前に、子が終了するのを待つことは常に良い習慣です。STDIN
STDOUT
STDERR
実行されたプロセスを待ちたい場合は、Bash で次のようなことを試すことができます。
#!/usr/bin/bash
cpid=()
for exe in script1 script2 script3; do
$exe&
cpid[$!]="$exe";
done
while [ ${#cpid[*]} -gt 0 ]; do
for i in ${!cpid[*]}; do
[ ! -d /proc/$i ] && echo UNSET $i && unset cpid[$i]
done
echo DO SOMETHING HERE; sleep 2
done
このスクリプトは、最初に script# を非同期的に起動し、pid を という配列に格納しcpid
ます。次にループがあります。それらがまだ実行されていることを参照します (/proc/ が存在します)。存在しない場合は、テキストUNSET <PID>
が表示され、PID が配列から削除されます。
一部が非常に長く実行されているかのように防弾ではなくDO SOMETHING HERE
、同じ PID を別のプロセスに追加できます。しかし、平均的な環境ではうまく機能します。
しかし、このリスクも軽減できます。
#!/usr/bin/bash
# Enable job control and handle SIGCHLD
set -m
remove() {
for i in ${!cpid[*]}; do
[ ! -d /proc/$i ] && echo UNSET $i && unset cpid[$i] && break
done
}
trap "remove" SIGCHLD
#Start background processes
cpid=()
for exe in "script1 arg1" "script2 arg2" "script3 arg3" ; do
$exe&
cpid[$!]=$exe;
done
#Non-blocking wait for background processes to stop
while [ ${#cpid[*]} -gt 0 ]; do
echo DO SOMETHING; sleep 2
done
このバージョンでは、非同期サブプロセスが終了したときに、スクリプトが SIGCHLD シグナルを受信できるようになります。SIGCHLD を受信すると、存在しない最初のプロセスを非同期的に探します。待機中のループが大幅に削減されます。