gpt4 book ai didi

perl - 无法让系统命令在perl脚本中超时

转载 作者:行者123 更新时间:2023-12-04 02:33:10 25 4
gpt4 key购买 nike

我四处浏览并阅读了一些关于获取命令在一段时间后停止运行的其他问题,但我尝试的一切都不起作用。

命令会在指定的时间后停止(它会返回终端提示符一小段时间),但会继续执行,不会停止。

这是我的代码:

#!/usr/bin/perl

use strict;
use warnings;


use Try::Tiny;

try {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm 5;
system("ping 192.168.1.1");
alarm 0;
}
catch {
die $_ unless $_ eq "alarm\n";
print "timed out\n";
};
exit;

终端中的输出如下所示:

PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.98 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=3.13 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=3.20 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=3.17 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=3.16 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=3.11 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=3.18 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=3.20 ms
64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=3.22 ms
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=3.20 ms
skilo@hp-xubuntu:~/perlstuff$ 64 bytes from 192.168.1.1: icmp_seq=11 ttl=64 time=3.06 ms
64 bytes from 192.168.1.1: icmp_seq=12 ttl=64 time=3.19 ms
64 bytes from 192.168.1.1: icmp_seq=13 ttl=64 time=3.21 ms
64 bytes from 192.168.1.1: icmp_seq=14 ttl=64 time=3.21 ms

注意它是如何尝试停止但不能停止的。

最佳答案

perl 'system' 内置函数 fork 你的进程,在 fork 创建的子进程中,它执行 'ping' 程序。然后,父进程等待子进程完成。

您的闹钟计时器和信号处理程序会中断等待进程,然后终止父进程,让子进程在后台运行。

您需要做的是:

  1. 报警超时后,通过发送信号杀死子进程
  2. 您仍然应该(手动)等待进程,以避免出现僵尸。

试试这个:

#!/usr/bin/perl

use strict;
use warnings;



eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm 5;
system("ping -v 192.168.1.1");
alarm 0;
};
if ($@) {
die $@ unless $@ eq "alarm\n";
print "timed out\n";
kill 2, -$$;
wait;
};
exit;

注意:我的系统上没有 Try::Tiny,所以我用老式的 eval block 替换了它。但它的工作原理应该是一样的。

这个“kill”命令需要一个信号编号(我使用 2 表示 SIGINT,相当于按 ctrl-c)和一个或多个要终止的进程。 $$是当前进程的pid;负值会杀死与当前进程关联的整个进程组(这实际上意味着所有子进程)。请注意,这不是完全可移植的——如果您发现它在您的系统上不起作用,那么您将需要能够找到子进程的实际 PID。为了能够做到这一点,您应该将系统替换为对 fork 的调用,然后调用 exec,如下所示:

#!/usr/bin/perl

use strict;
use warnings;


my $childPid;
eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm 5;
if ($childPid = fork()) {
wait();
} else {
exec("ping -v 192.168.1.1");
}
alarm 0;
};
if ($@) {
die $@ unless $@ eq "alarm\n";
print "timed out\n";
kill 2, $childPid;
wait;
};
exit;

关于perl - 无法让系统命令在perl脚本中超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21245404/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com