How can I reinitialize Perl's STDIN/STDOUT/STDERR?

╄→尐↘猪︶ㄣ 提交于 2020-01-09 09:37:32

问题


I have a Perl script which forks and daemonizes itself. It's run by cron, so in order to not leave a zombie around, I shut down STDIN,STDOUT, and 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();
  }

The question I have is: I'd like to restore at least STDOUT after this point (it would be nice to restore the other 2). But what magic symbols do I need to use to re-open STDOUT as what STDOUT used to be?

I know that I could use "/dev/tty" if I was running from a tty (but I'm running from cron and depending on stdout elsewhere). I've also read tricks where you can put STDOUT aside with open SAVEOUT,">&STDOUT", but just the act of making this copy doesn't solve the original problem of leaving a zombie around.

I'm looking to see if there's some magic like open STDOUT,"|-" (which I know isn't it) to open STDOUT the way it's supposed to be opened.


回答1:


If it's still useful, two things come to mind:

  1. You can close STDOUT/STDERR/STDIN in just the child process (i.e. if (!fork()). This will allow the parent to still use them, because they'll still be open there.

  2. I think you can use the simpler close(STDOUT) instead of opening it to /dev/null.

For example:

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:


# copy of the file descriptors

open(CPERR, ">&STDERR");

# redirect stderr in to warning file

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

# close the redirected filehandles

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

# restore stdout and stderr

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

#I hope this works for you.

#-Hariprasad AJ




回答3:


Once closed, there's no way to get it back.

Why do you need STDOUT again? To write messages to the console? Use /dev/console for that, or write to syslog with Sys::Syslog.

Honestly though, the other answer is correct. You must save the old stdout (cloned to a new fd) if you want to reopen it later. It does solve the "zombie" problem, since you can then redirect fd 0 (and 1 & 2) to /dev/null.



来源:https://stackoverflow.com/questions/1348639/how-can-i-reinitialize-perls-stdin-stdout-stderr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!