2

Bash コマンドを実行する必要があります。ただし、このコマンドの実行には数分かかります。

このコマンドを正常に (同期的に) 実行すると、コマンドの実行が完了するまでアプリケーションがハングします。

Perl スクリプトから非同期で Bash コマンドを実行するにはどうすればよいですか?

4

3 に答える 3

2

これを行う通常の方法は、fork. execスクリプト フォークを作成すると、子は Bash スクリプトでまたはを呼び出しますsystem(子が Bash スクリプトのリターン コードを処理する必要があるか、それ以外の方法で対話する必要があるかによって異なります)。

次に、親はおそらくwaitand/orSIGCHILDハンドラーの組み合わせを必要とするでしょう。

それを処理する方法の正確な詳細は、状況と正確なニーズに大きく依存します.

于 2013-05-27T21:24:32.247 に答える
2

結果を気にしない場合は、そのまま使用できます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パッケージを使用できます。とにかく、呼び出し元が終了する前に、子が終了するのを待つことは常に良い習慣です。STDINSTDOUTSTDERR

実行されたプロセスを待ちたい場合は、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 を受信すると、存在しない最初のプロセスを非同期的に探します。待機中のループが大幅に削減されます。

于 2013-05-27T10:15:25.423 に答える