加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

coreutils超时模拟perl

发布时间:2020-12-16 06:13:16 所属栏目:大数据 来源:网络整理
导读:我试图使用perl替换超时(需要在centos5中) 这里的脚本: #!/usr/bin/perluse strict;my $pid=$$;my $timeout=shift;my @args=@ARGV;eval { local $SIG{ALRM} = sub { print "Timed OUT!n"; exit 142; kill 9,$pid; }; alarm($timeout); system(@args);};exi
我试图使用perl替换超时(需要在centos5中)

这里的脚本:

#!/usr/bin/perl
use strict;
my $pid=$$;
my $timeout=shift;
my @args=@ARGV;
eval {
        local $SIG{ALRM} = sub {
          print "Timed OUT!n";
          exit 142;
          kill 9,$pid;
        };
        alarm($timeout);
        system(@args);
};
exit $?;

测试时我发现:

这里都很好

time /tmp/timeout 3 sleep 6
Timed OUT!

real    0m3.007s
user    0m0.000s
sys     0m0.004s

但这里都很糟糕

time echo `/tmp/timeout 3 sleep 6`
Timed OUT!

real    0m6.009s
user    0m0.000s
sys     0m0.004s

在我使用/usr/bin/timeout测试的debian系统上:

time echo `/usr/bin/timeout 3 sleep 6`


real    0m3.004s
user    0m0.000s
sys     0m0.000s

所以问题

>为什么perl脚本工作如此奇怪?
>有没有任何真正的工作方式在perl上写入超时,它将与二进制超时一样工作?

请注意,我知道/usr/share/doc/bash-3.2/scripts/timeout,我也发现它的行为与我的perl方法相同

另请注意,我无法在此脚本的目标服务器上安装CPAN模块

我尝试使用exec()但在这种情况下它不处理sub中的信号.

UPD

用@rhj中的脚本(必须修复一下)

#!/usr/bin/perl
use strict;
use warnings;
my $PID=$$;
my $timeout=shift;
my @args=@ARGV;

my $pid = fork();
defined $pid or die "fork: $!";
$pid == 0 && exec(@args);

my $timed_out = 0;
$SIG{ALRM} = sub { $timed_out = 1; die; };
alarm $timeout;
eval { waitpid $pid,0 };
alarm 0;
if ($timed_out) {
    print "Timed out!n";
    kill 9,$pid;
    kill 9,$PID;
}
elsif ($@) {
    warn "error: $@n";
}

它通过了上面的测试,但在调用外部脚本的情况下失败:

RUN_SCRIPT

#!/bin/sh
sleep 6

test.sh

#!/bin/sh
a=`./timeout.pl 2 ./run_script.sh`

产量

$time ./test.sh 

real    0m6.020s
user    0m0.004s
sys     0m0.008s

解决方法

这个版本应该始终有效:

#!/usr/bin/perl
use strict;
use warnings;
my $pid=$$;
my $timeout=shift;
my @args=@ARGV;

my $pid = fork();
defined $pid or die "fork: $!";
$pid == 0 && exec(@args);

my $timed_out = 0;
$SIG{ALRM} = sub { $timed_out = 1; die; };
alarm $timeout;
eval { waitpid $pid,$pid;
}
elsif ($@) {
    warn "error: $@n";
}

但它不会处理exec()调用中的错误.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读