如何使用 Perl 杀死耗时的进程或卡住的进程(通过
system
命令生成)。如何杀死使用
system
命令启动的进程花费太多时间或卡在某个地方。
3 回答
如果您希望在同一脚本中终止由 system() 调用的进程,则无法获取或终止它的 PID,因为 system() 调用在进程完成之前不会返回。相反,您可以使用 fork() 创建一个新进程,并在 exec() 新创建的进程中执行最初由 system() 调用的进程。fork() 将返回子进程的 PID,然后您可以随时使用 kill() 杀死它。
http://perldoc.perl.org/functions/fork.html
Perl FAQ 的第 8 节包含
如何使慢速事件超时?
使用该
alarm
函数,可能与信号处理程序一起使用,如Perlipc中的信号和 Camel 中的“信号”部分所述。您可以改用 CPAN 提供的更灵活的Sys::AlarmCall模块。该
alarm
功能并非在所有版本的 Windows 上都实现。检查您的特定 Perl 版本的文档。
perlipc 文档的“信号”部分包含
信号处理也用于 Unix 中的超时。虽然在一个
eval{}
块内受到安全保护,但您设置一个信号处理程序来捕获警报信号,然后安排在几秒钟内将一个信号发送给您。然后尝试您的阻止操作,在完成后清除警报,但在您退出eval{}
阻止之前清除警报。如果它熄灭,您将用于die
跳出街区。这是一个例子:
my $ALARM_EXCEPTION = "alarm clock restart"; eval { local $SIG{ALRM} = sub { die $ALARM_EXCEPTION }; alarm 10; flock(FH, 2) # blocking write lock || die "cannot flock: $!"; alarm 0; }; if ($@ && $@ !~ quotemeta($ALARM_EXCEPTION)) { die }
如果超时的操作是
system
或qx
,这种技术很容易产生僵尸。如果这对您很重要,您需要自己做fork
andexec
,并杀死错误的子进程。对于更复杂的信号处理,您可能会看到标准POSIX模块。遗憾的是,这几乎完全没有文档记录,但
t/lib/posix.t
来自 Perl 源代码分发的文件中有一些示例。
建议使用 fork 和 exec,主要作为安全预防措施(用户输入)。
但是,如果您不关心用户输入并且知道您已经开始使用系统的进程,那么您可以打开一个到任务列表或 ls 调用的管道,用 grep 处理它们以找到您所困扰的进程,然后发送终止信号到那些进程。