作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
由于我公司的要求,我刚刚从 php 转到 perl,所以即使这可能是一个愚蠢的问题,现在也有点紧张。
我通过 debian 软件包在服务器上部署了一个小的 perl 脚本。我已经弄清楚了这一切,所以这一切都很酷。
现在通过 SSH 连接从另一台服务器调用此脚本,并且脚本将其所有操作记录回该服务器。为此,我使用 Log::Log4perl。
其中一个任务需要很长时间,并且在此过程中还运行了一些其他脚本。 ssh 连接的超时设置为 5 分钟,除非我重新登录。所以我想出我会创建一个子进程来运行任务并让父进程每 90(或其他)秒记录一次。我的问题是我不想使用 sleep ,因为如果任务完成得越早,它就会弄乱日志。我也尝试过使用 Time、Time::HiRes 和闹钟,但它们都以某种方式弄乱了我的日志。
这是我的代码:
$log->info("uid $uid: calling the configure script for operation $mode,on $dst_path");
my $pid = fork();
die "Could not fork\n" if not defined $pid;
if ( $pid == 0 ) {
configure( $script_dir, $mode, $node, $uid, $gid); # this also uses a parallel process in its execution, but we don't have a non blocking wait
}
while ( !waitpid( $pid, WNOHANG ) ) {
sleep(90);
if ( !$pid ) {
$log->info("Still waiting for the process to finish"); # this should come up every 90 seconds of so
}
}
$log->info("uid $uid: configure script executed"); # this should come up only once, now I get it every 90 seconds
# do other stuff here after the execution of the configure sub is done
不幸的是,我继承了这个架构,不能改变它,因为有很多服务基于它。
最佳答案
不想 sleep 可以打select
超时。为了可靠地实现这一点,您可以使用 self-pipe trick这涉及创建一个管道,在 SIGCHLD
处理程序中写入管道,并使 select
调用等待管道的读取句柄。
这是一个简单的例子:
#!/usr/bin/perl
use strict;
use warnings;
use Errno qw(EINTR);
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);
use Symbol qw(gensym);
sub make_non_blocking {
my $handle = shift;
my $flags = fcntl($handle, F_GETFL, 0)
or die("F_GETFL: $!");
fcntl($handle, F_SETFL, $flags | O_NONBLOCK)
or die("F_SETFL: $!");
}
my ($read_handle, $write_handle) = (gensym, gensym);
pipe($read_handle, $write_handle)
or die("pipe: $!");
make_non_blocking($read_handle);
make_non_blocking($write_handle);
local $SIG{CHLD} = sub {
syswrite($write_handle, "\0", 1);
};
my $pid = fork();
die("fork: $!") if !defined($pid);
if ($pid == 0) {
sleep(10);
exit;
}
my $rin = '';
vec($rin, fileno($read_handle), 1) = 1;
while (1) {
my $nfound = select(my $rout = $rin, undef, undef, 2);
if ($nfound < 0) {
# Error. Must restart the select call on EINTR.
die("select: $!") if $! != EINTR;
}
elsif ($nfound == 0) {
# Timeout.
print("still running...\n");
}
else {
# Child exited and pipe was written to.
last;
}
}
waitpid($pid, 0);
close($read_handle);
close($write_handle);
关于linux - 只要子进程仍在运行,就在父进程中每 90 秒在 perl 中记录一次消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28902533/
我是一名优秀的程序员,十分优秀!