什么';在perl中安全运行这个容易出错的系统调用的正确方法是什么?
因此,作为OSX computer lab系统启动脚本的一部分,我正在运行一个名为systemsetup的内置shell命令,以便将系统与网络时间服务器同步。它在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
#!/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
。