perl父进程挂起,等待子进程读取stdin

perl父进程挂起,等待子进程读取stdin,perl,io,Perl,Io,我有一个模拟tee命令的perl脚本,这样我就可以将输出写入终端和日志文件。它的工作原理是这样的(错误检查&c省略) $pid=open(STDOUT,'-|'); #上面是perl魔术,它分叉一个进程并用 #子对象的STDIN是管道的一端,而父对象的STDOUT(在 #(这个案例)是另一个。 如果($pid==0) { #孩子。 #打开日志文件 而() { #打印到标准输出和日志文件 } #关闭日志文件 出口 } #母公司 打开STDERR,'>&STDOUT'; #执行大量系统(“…”)调用

我有一个模拟tee命令的perl脚本,这样我就可以将输出写入终端和日志文件。它的工作原理是这样的(错误检查&c省略)

$pid=open(STDOUT,'-|');
#上面是perl魔术,它分叉一个进程并用
#子对象的STDIN是管道的一端,而父对象的STDOUT(在
#(这个案例)是另一个。
如果($pid==0)
{
#孩子。
#打开日志文件
而()
{
#打印到标准输出和日志文件
}
#关闭日志文件
出口
}
#母公司
打开STDERR,'>&STDOUT';
#执行大量系统(“…”)调用
关闭STDERR;
关闭STDOUT;
出口
这有时会挂起,如果您查看进程和所述进程的堆栈,父进程总是挂起,等待子进程退出,而子进程挂起从文件(必须是STDIN,因为没有其他文件)读取内容

我不知道如何处理这件事。如果您是从一个未连接到控制台的shell运行程序(在普通shell中运行脚本效果良好),那么问题似乎就会发生。最近,该脚本中唯一发生变化的代码是添加了一个打开/关闭的文件,只是为了触摸它(在脚本到达这个“tee”代码之前)


以前有没有人遇到过这样的问题,或者有没有人建议我如何解决这个问题?谢谢。

好吧,经过一些实验之后,打开
标准输出似乎至少是部分原因。我的代码现在如下所示:

$pid = open($handle, '|-');
if ($pid == 0)
{
    # Child. 
    # Open log file
    while (<STDIN>)
    {
       # print to STDOUT and log file
    }
    #close log files
    exit;
}
# parent
open my $oldout, '>&STDOUT';
open my $olderr, '>&STDERR';
open STDOUT, '>&', $handle;
open STDERR, '>&', $handle;
# do lots of system("...") calls
open STDOUT, '>&', $oldout;
open STDERR, '>&', $olderr;
close $handle or die "Log child exited unexpectedly: $!\n";
exit;
$pid=open($handle,|-);
如果($pid==0)
{
#孩子。
#打开日志文件
而()
{
#打印到标准输出和日志文件
}
#关闭日志文件
出口
}
#母公司
打开我的$oldout,“>&STDOUT”;
打开我的$olderr,'>&STDERR';
打开标准输出“>”和“,$handle;
打开STDERR,'>&',$handle;
#执行大量系统(“…”)调用
打开标准输出“>”和“,$oldout;
打开标准'>&',$olderr;
关闭$handle或死亡“日志子项意外退出:$!\n”;
出口

如果没有其他东西,看起来更干净(但仍然比我想要的更混乱,因为我不知道如果这些DUP中的任何一个出现错误该怎么办)。但我仍然不清楚为什么在代码中更早地打开和关闭句柄会对这一位产生如此大的影响。

分离时是否总是会发生这种情况?STDOUT是在cron-ed命令行还是在程序中被提前重定向的?我看不出问题所在,对我来说,这两种方式都有效。我更新了我的帖子,用了我想尝试的具体内容和我正在使用的确切代码。我在想缓冲/标准输入会被搞砸。例如,最后的打印(最后的缓冲区)不会被刷新。
$pid = open($handle, '|-');
if ($pid == 0)
{
    # Child. 
    # Open log file
    while (<STDIN>)
    {
       # print to STDOUT and log file
    }
    #close log files
    exit;
}
# parent
open my $oldout, '>&STDOUT';
open my $olderr, '>&STDERR';
open STDOUT, '>&', $handle;
open STDERR, '>&', $handle;
# do lots of system("...") calls
open STDOUT, '>&', $oldout;
open STDERR, '>&', $olderr;
close $handle or die "Log child exited unexpectedly: $!\n";
exit;