Как я могу повторно инициализировать Perl STDIN/STDOUT/STDERR?
У меня есть Perl script, который развивает и демонзирует себя. Он управляется 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?
Я знаю, что я мог бы использовать "/dev/tty", если бы я бежал от tty (но я бегу от cron и в зависимости от stdout в другом месте). Я также читал трюки, в которых вы можете поместить STDOUT в сторону open SAVEOUT,">&STDOUT"
, но только акт создания этой копии не решает исходную проблему оставления зомби.
Я хочу посмотреть, есть ли какая-то магия, вроде open STDOUT,"|-"
(которая, как я знаю, не так), чтобы открыть STDOUT так, как она должна быть открыта.
Ответы
Ответ 1
Если это все еще полезно, на ум приходят две вещи:
-
Вы можете закрыть STDOUT/STDERR/STDIN только в дочернем процессе (т.е. if (! fork()). Это позволит родителям все еще использовать их, потому что они все равно будут открыты там.
-
Я думаю, вы можете использовать более простое закрытие (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();
}
Ответ 2
# копия файловых дескрипторов
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: $!";
# Я надеюсь, что это сработает для вас.
# - Харипрасад AJ
Ответ 3
После закрытия нет способа вернуть его.
Зачем вам снова нужен STDOUT? Чтобы писать сообщения на консоль? Для этого используйте /dev/console или напишите в syslog с Sys:: Syslog.
Честно говоря, другой ответ правильный. Вы должны сохранить старый stdout (клонированный к новому fd), если вы хотите повторно открыть его позже. Он решает проблему "зомби", так как вы можете перенаправить fd 0 (и 1 и 2) в/dev/null.