如何重新初始化Perl的STDIN / STDOUT / STDERR?

时间:2009-08-28 18:29:39

标签: perl redirect stdout stdin stderr

我有一个Perl脚本,它自己分叉和守护。它由cron运行,所以为了不留下僵尸,我关闭了STDIN,STDOUT和STDERR:

open STDIN, '/dev/null'   or die "Can't read /dev/null: $!";
open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
if (!fork()) {
  do_some_fork_stuff();
  }

我的问题是:我想在此之后恢复至少STDOUT(恢复其他2会很好)。但是我需要使用什么魔术符号来重新打开STDOUT,就像STDOUT曾经一样?

我知道如果我是从tty运行的话我可以使用“/ dev / tty”(但我是从cron运行并依赖于其他地方的stdout)。我也读过一些技巧,你可以把STDOUT放在open SAVEOUT,">&STDOUT"旁边,但只是制作这个副本的行为并不能解决留下僵尸的原始问题。

我正在寻找是否有像open STDOUT,"|-"这样的魔法(我知道不是这样)以打开它应该打开的方式打开STDOUT。

3 个答案:

答案 0 :(得分:15)

文件描述符的副本

open(CPERR, ">&STDERR");

#将stderr重定向到警告文件

open(STDERR, ">>xyz.log") || die "Error stderr: $!";

#关闭重定向的文件句柄

close(STDERR) || die "Can't close STDERR: $!";

#rescovery stdout和stderr

open(STDERR, ">&CPERR") || die "Can't restore stderr: $!";

#I希望这适合你。

# - Hariprasad AJ

答案 1 :(得分:5)

如果它仍然有用,我会想到两件事:

  1. 你可以在子进程中关闭STDOUT / STDERR / STDIN(即if(!fork())。这将允许父进程仍然使用它们,因为它们仍然会在那里打开。

  2. 我认为您可以使用更简单的关闭(STDOUT)而不是将其打开到/ dev / null。

  3. 例如:

    if (!fork()) {
        close(STDIN) or die "Can't close STDIN: $!\n";
        close(STDOUT) or die "Can't close STDOUT: $!\n";
        close(STDERR) or die "Can't close STDERR: $!\n";
        do_some_fork_stuff();
    }
    

答案 2 :(得分:4)

关闭后,无法取回它。

为什么你需要STDOUT?要将消息写入控制台?使用/ dev / console,或使用Sys :: Syslog写入syslog。

老实说,另一个答案是正确的。如果要稍后重新打开,则必须保存旧的stdout(克隆到新的fd)。它解决了“僵尸”问题,因为您可以将fd 0(和1& 2)重定向到/ dev / null。