在 Perl 中执行进程,使用 IPC 停止、恢复、终止选项
execute process in Perl with options for stopping,resuming,killing using IPC
我几乎不知道分叉。我试图研究,但我找不到一个简单的例子来说明如何做这些事情。为了windows我找到了一个很好的模块,写了这段代码,这就是我想要的。
Win32::Process::Create( my $ProcessObj,
"$jobs{$id}->{path}", "execute job", 0, NORMAL_PRIORITY_CLASS, "." )
|| die ErrorReport();
print "Available commands:\n1.Suspend\n2.Resume\n3.Kill\n";
while (1) {
chomp( my $input = <STDIN> );
if ( $input eq "1" ) {
$ProcessObj->Suspend();
}
if ( $input eq "2" ) {
$ProcessObj->Resume();
}
if ( $input eq "3" ) {
print "Returned to main menu.\n";
$ProcessObj->Kill(0);
return;
}
}
所以我的问题是是否有办法通过分叉来做到这一点?
这是我的分叉尝试:
unless ( $pid = fork) {
unless (fork) {
exec "$jobs{$id}->{path}";
die "exec failed!";
}
exit 0;
}
waitpid($pid, 0);
我有一个程序每 3 秒打印一次 Hello world,我想暂停它,恢复它并终止它,如果这个例子有帮助的话。
Forks::Super
使这变得简单且与平台无关。
use Forks::Super;
...
my $pid = fork { exec => $jobs{$id}->{path} };
...
$pid->suspend;
...
$pid->resume;
...
$pid->kill; # or $pid->kill('TERM'), $pid->kill('QUIT'), etc.
如果你必须用手走,要使用的信号是'SIGSTOP'
和'SIGCONT'
。
一个command-line演示
perl -wE'
$pid = fork // die "Cant fork: $!";
if ($pid == 0) {
for (1..6) { say "\tkid ..."; sleep 1; };
say "\tKID DONE"; exit;
};
sleep 3;
kill "STOP", $pid;
for (1..2) { say "Parent here!"; sleep 1};
kill "CONT", $pid;
wait;
'
打印
kid ...
kid ...
kid ...
Parent here!
Parent here!
kid ...
kid ...
kid ...
KID DONE
那么您需要在 STDIN
驱动的管理中实现它。
不过我建议尝试解决Forks::Super的安装问题,来自mob的回答。
一个STDIN
受控实例。分叉进程和 parent 写入文件进行测试。
use warnings;
use strict;
use feature 'say';
#use IO::Handle; # needed pre v5.16 (for autoflush)
my $fh_kid;
$SIG{INT} = sub { close $fh_kid; exit 1 };
my $file = 'kidfile.out';
open $fh_kid, '>', $file or die "Can't open $file: $!";
$fh_kid->autoflush;
my $pid = fork // die "Can't fork: $!";
if ($pid == 0) {
$SIG{TERM} = sub { close $fh_kid; exit 1 };
for (1..20) {
say $fh_kid "\tkid, $_";
sleep 1;
}
exit;
}
say "Parent: started $pid";
while (1) {
chomp (my $input = <STDIN>);
if (not $input) {
close $fh_kid;
last;
}
if ($input == 1) {
kill 'STOP', $pid;
say "Parent: STOP-ed $pid";
say $fh_kid "Parent STOP-ed $pid";
}
elsif ($input == 2) {
say "Parent: CONT the $pid";
kill 'CONT', $pid;
}
elsif ($input == 3) {
close $fh_kid;
kill 'TERM', $pid;
say "Parent: TERM-ed the $pid";
}
}
my $gone = waitpid $pid, 0;
if ($gone > 0) { say "Child $gone exited with: $?" }
elsif ($gone < 0) { say "No such process ($gone), reaped already?" }
else { say "Still out there?" }
这需要更多详细信息,但它确实显示了涉及的内容。
输出(带注释)
Parent: started 19628
1 # entered a few seconds after starting
Parent: STOP-ed 19628
2 # after waiting for a minute
Parent: CONT the 19628
3 # after waiting for a few more seconds
Parent: TERM-ed the 19628
^C # quit STDIN
我们允许孩子打印到一个文件几秒钟(所以几次)然后 STOP
它 (1),然后稍等片刻然后 CONT
inue the child (2) 并在杀死它之前让它再打印几次 (3)。
输出 kidfile.out
有来自 child 的几行,然后来自 parent 的一行,然后来自 child 的更多行,确认child 暂停、恢复和停止。
我几乎不知道分叉。我试图研究,但我找不到一个简单的例子来说明如何做这些事情。为了windows我找到了一个很好的模块,写了这段代码,这就是我想要的。
Win32::Process::Create( my $ProcessObj,
"$jobs{$id}->{path}", "execute job", 0, NORMAL_PRIORITY_CLASS, "." )
|| die ErrorReport();
print "Available commands:\n1.Suspend\n2.Resume\n3.Kill\n";
while (1) {
chomp( my $input = <STDIN> );
if ( $input eq "1" ) {
$ProcessObj->Suspend();
}
if ( $input eq "2" ) {
$ProcessObj->Resume();
}
if ( $input eq "3" ) {
print "Returned to main menu.\n";
$ProcessObj->Kill(0);
return;
}
}
所以我的问题是是否有办法通过分叉来做到这一点? 这是我的分叉尝试:
unless ( $pid = fork) {
unless (fork) {
exec "$jobs{$id}->{path}";
die "exec failed!";
}
exit 0;
}
waitpid($pid, 0);
我有一个程序每 3 秒打印一次 Hello world,我想暂停它,恢复它并终止它,如果这个例子有帮助的话。
Forks::Super
使这变得简单且与平台无关。
use Forks::Super;
...
my $pid = fork { exec => $jobs{$id}->{path} };
...
$pid->suspend;
...
$pid->resume;
...
$pid->kill; # or $pid->kill('TERM'), $pid->kill('QUIT'), etc.
如果你必须用手走,要使用的信号是'SIGSTOP'
和'SIGCONT'
。
一个command-line演示
perl -wE'
$pid = fork // die "Cant fork: $!";
if ($pid == 0) {
for (1..6) { say "\tkid ..."; sleep 1; };
say "\tKID DONE"; exit;
};
sleep 3;
kill "STOP", $pid;
for (1..2) { say "Parent here!"; sleep 1};
kill "CONT", $pid;
wait;
'
打印
kid ... kid ... kid ... Parent here! Parent here! kid ... kid ... kid ... KID DONE
那么您需要在 STDIN
驱动的管理中实现它。
不过我建议尝试解决Forks::Super的安装问题,来自mob的回答。
一个STDIN
受控实例。分叉进程和 parent 写入文件进行测试。
use warnings;
use strict;
use feature 'say';
#use IO::Handle; # needed pre v5.16 (for autoflush)
my $fh_kid;
$SIG{INT} = sub { close $fh_kid; exit 1 };
my $file = 'kidfile.out';
open $fh_kid, '>', $file or die "Can't open $file: $!";
$fh_kid->autoflush;
my $pid = fork // die "Can't fork: $!";
if ($pid == 0) {
$SIG{TERM} = sub { close $fh_kid; exit 1 };
for (1..20) {
say $fh_kid "\tkid, $_";
sleep 1;
}
exit;
}
say "Parent: started $pid";
while (1) {
chomp (my $input = <STDIN>);
if (not $input) {
close $fh_kid;
last;
}
if ($input == 1) {
kill 'STOP', $pid;
say "Parent: STOP-ed $pid";
say $fh_kid "Parent STOP-ed $pid";
}
elsif ($input == 2) {
say "Parent: CONT the $pid";
kill 'CONT', $pid;
}
elsif ($input == 3) {
close $fh_kid;
kill 'TERM', $pid;
say "Parent: TERM-ed the $pid";
}
}
my $gone = waitpid $pid, 0;
if ($gone > 0) { say "Child $gone exited with: $?" }
elsif ($gone < 0) { say "No such process ($gone), reaped already?" }
else { say "Still out there?" }
这需要更多详细信息,但它确实显示了涉及的内容。
输出(带注释)
Parent: started 19628 1 # entered a few seconds after starting Parent: STOP-ed 19628 2 # after waiting for a minute Parent: CONT the 19628 3 # after waiting for a few more seconds Parent: TERM-ed the 19628 ^C # quit STDIN
我们允许孩子打印到一个文件几秒钟(所以几次)然后 STOP
它 (1),然后稍等片刻然后 CONT
inue the child (2) 并在杀死它之前让它再打印几次 (3)。
输出 kidfile.out
有来自 child 的几行,然后来自 parent 的一行,然后来自 child 的更多行,确认child 暂停、恢复和停止。