gpt4 book ai didi

linux - 只要子进程仍在运行,就在父进程中每 90 秒在 perl 中记录一次消息

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:16:58 26 4
gpt4 key购买 nike

由于我公司的要求,我刚刚从 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/

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