Как я могу заново инициализировать Perl STDIN / STDOUT / STDERR? - PullRequest
16 голосов
/ 28 августа 2009

У меня есть скрипт 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, как это было раньше?

Я знаю, что мог бы использовать "/ dev / tty", если бы я работал с tty (но я работаю с cron и зависит от stdout в другом месте). Я также читал трюки, в которых вы можете отложить STDOUT с помощью open SAVEOUT,">&STDOUT", но сам процесс создания этой копии не решает исходную проблему оставления зомби вокруг.

Я смотрю, есть ли какая-нибудь магия типа open STDOUT,"|-" (которую я знаю, не так ли), чтобы открыть STDOUT так, как это должно быть открыто.

Ответы [ 3 ]

15 голосов
/ 12 ноября 2009

# копия файловых дескрипторов

open(CPERR, ">&STDERR");

# перенаправить stderr в файл предупреждения

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

# закрыть перенаправленные файловые дескрипторы

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

# восстановление stdout и stderr

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

# Я надеюсь, что это работает для вас.

# - Hariprasad AJ

5 голосов
/ 29 августа 2009

Если это все еще полезно, на ум приходят две вещи:

  1. Вы можете закрыть STDOUT / STDERR / STDIN только в дочернем процессе (т. Е. Если (! Fork ()). Это позволит родителям по-прежнему использовать их, потому что они все еще будут открыты там.

  2. Я думаю, что вы можете использовать более простое закрытие (STDOUT) вместо того, чтобы открывать его в /dev/null.

Например:

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();
}
4 голосов
/ 28 августа 2009

После закрытия нет способа вернуть его обратно.

Зачем вам снова нужен STDOUT? Писать сообщения в консоль? Для этого используйте / dev / console или напишите в syslog с помощью Sys :: Syslog.

Честно говоря, другой ответ правильный. Вы должны сохранить старый стандартный вывод (клонированный в новый файл), если вы хотите открыть его позже. Это решает проблему «зомби», поскольку вы можете перенаправить fd 0 (и 1 & 2) в /dev/null.

...