Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';在perl中安全运行这个容易出错的系统调用的正确方法是什么?_Perl_Macos_Error Handling - Fatal编程技术网

什么';在perl中安全运行这个容易出错的系统调用的正确方法是什么?

什么';在perl中安全运行这个容易出错的系统调用的正确方法是什么?,perl,macos,error-handling,Perl,Macos,Error Handling,因此,作为OSX computer lab系统启动脚本的一部分,我正在运行一个名为systemsetup的内置shell命令,以便将系统与网络时间服务器同步。它在perl脚本中运行,如下所示 #!/usr/bin/perl system("systemsetup -setusingnetworktime off"); system("systemsetup -setusingnetworktime on"); 首先将其翻转为“关闭”可确保它在打开时更新 问题是,该命令经常抛出以下错误writ

因此,作为OSX computer lab系统启动脚本的一部分,我正在运行一个名为systemsetup的内置shell命令,以便将系统与网络时间服务器同步。它在perl脚本中运行,如下所示

#!/usr/bin/perl

system("systemsetup -setusingnetworktime off");
system("systemsetup -setusingnetworktime on");
首先将其翻转为“关闭”可确保它在打开时更新

问题是,该命令经常抛出以下错误
writeconfig[1841:903]***-[NSMachPort handlePortMessage:]:由于连接或端口无效而丢弃传入的DO消息,然后根据运行shell或脚本的位置暂停shell或脚本的执行

实际上,在500个每天开机运行脚本的实验室系统上,这种情况很少发生,我每隔几周只在单个系统上注意到一个问题。奇怪的是,它实际上很容易在测试中复制

所以我的理解是,这显然是systemsetup中的一个bug,抛出了这个错误,但我确信有一种方法可以让我的perl脚本优雅地处理它,对吗


目前我想到的最好的方法是
systemsetup-设置使用networktime off&>/dev/null
,它将STDOUT和STDERR都传输到/dev/null。

如果命令可能会出错并挂起脚本,一个好的防御方法是使用
SIGALRM
处理程序使命令超时

sub system_with_timeout {
    my ($timeout, @command) = @_;
    local $SIG{ALRM} = sub { die "Timeout\n" };
    my $result;
    if ($timeout > 0) { alarm $timeout; }
    eval {
        $result = system(@command);
    };
    if ($@ =~ /Timeout/) {
        warn "@command timed out.\n";
        return -1;
    }
    return $result;
}
检查返回值以确保命令成功或是否超时

my $z = system_with_timeout(30, "systemsetup -setusingnetworktime off");
if ($z == 0) {
    # success ...
} elsif ($z == -1) {
    # timed out ... try it again ?
} else {
    # failed for some other reason ...
}

如果您不关心错误本身(例如,它只是一条警告消息),请务必重新引导命令的STDOUT/STDERR;尽管我个人建议重新定向到/tmp日志文件(而不是
/dev/null
),以防您需要对其他错误进行故障排除

如果您确实希望对此类错误执行特定操作,则可以检查返回代码(请参阅mobrule的答案),或者如果命令始终返回0,则捕获putput并对其进行错误过滤:

my @script_out = `systemsetup -setusingnetworktime off`;
# better yet use open with a pipe instead of backticks 
if (grep {/writeconfig.*dropping incoming DO message/} @script_out {
    # do error handling
}

只是好奇,让系统自动与网络时间服务器同步有什么错?我肯定最终会的,但在启动时我需要将记录的时间戳与当前时间戳进行比较,500台电脑意味着500个婴儿车电池,从现在起到机器生命周期结束,它们可能会或不会死亡。规则-我在回答中添加了额外的建议,以防
systemsetup
实际上没有通过返回码发出错误信号,不幸的是,这种情况相当普遍often@DVK-事实上;在本例中似乎是这样的。我建议在超时时返回
unde
(有点“不完整”)<代码>系统
将始终返回一个值。使用-1会导致与返回-1的程序发生冲突。因为这是一种错误情况,所以您希望尽可能最好地报告错误。@DVK很好的建议。使用_timeout实现
backticks_,或使用_timeout
实现
open-| _,功能相同,非常简单@Axeman-
系统
成功返回0。我不想执行错误的代码,因为我检查了
$returnval==0
,当我将
系统
更改为带有超时的
系统
调用时,忘记了检查
是否定义了$retval