System ()로 백그라운드에서 시작된 어린이 프로세스를 기다릴 수있는 방법은 무엇입니까?
-
06-09-2019 - |
문제
여러 매개 변수에 대한 쉘 스크립트를 실행하는 Perl 코드가있어서 단순화하기 위해 다음과 같은 코드가 있다고 가정합니다.
for $p (@a){
system("/path/to/file.sh $p&");
}
그 후 더 많은 일을하고 싶지만 계속하기 전에 모든 어린이 과정이 끝날 때까지 기다릴 수있는 방법을 찾을 수는 없습니다.
코드를 Fork () 사용하도록 변환하는 것은 어려울 것입니다. 더 쉬운 방법이 없습니까?
해결책
포크/exec/대기 사용은 그렇게 나쁘지 않습니다.
my @a = (1, 2, 3);
for my $p (@a) {
my $pid = fork();
if ($pid == -1) {
die;
} elsif ($pid == 0) {
exec '/bin/sleep', $p or die;
}
}
while (wait() != -1) {}
print "Done\n";
다른 팁
당신은 무언가를 변경해야하고, 포크를 사용하도록 코드를 변경해야 할 것입니다. 그러나 포크 사용에 대해 죽은 세트 인 경우 파일이 완료 될 때 파일을 터치하는 래퍼 쉘 스크립트를 사용할 수 있습니다. 파일의 존재를 확인하십시오.
래퍼는 다음과 같습니다.
#!/bin/bash
$*
touch /tmp/$2.$PPID
Perl 코드는 다음과 같습니다.
for my $p (@a){
system("/path/to/wrapper.sh /path/to/file.sh $p &");
}
while (@a) {
delete $a[0] if -f "/tmp/$a[0].$$";
}
그러나 나는 포킹 코드가 더 안전하고 명확하다고 생각합니다.
my @pids;
for my $p (@a) {
die "could not fork" unless defined(my $pid = fork);\
unless ($pid) { #child execs
exec "/path/to/file.sh", $p;
die "exec of file.sh failed";
}
push @pids, $pid; #parent stores children's pids
}
#wait for all children to finish
for my $pid (@pids) {
waitpid $pid, 0;
}
포크 ()로 변환하는 것은 어려울 수 있지만 올바른 도구입니다. System ()은 차단 호출입니다. 쉘을 실행하고 스크립트를 백그라운드에서 실행하도록 지시함으로써 비 블로킹 동작을 받고 있습니다. 즉, Perl은 아이들의 PID가 무엇인지 전혀 모른다는 것을 의미합니다. 즉, 대본이 무엇을 기다릴지 모릅니다.
PIDS를 PERL 스크립트까지 통신하려고 시도 할 수 있지만 빠르게 손을 떼십시오. 포크 ()를 사용하십시오.
제휴하지 않습니다 StackOverflow