Подтвердить что ты не робот

Как я могу повторно инициализировать 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 так, как она должна быть открыта.

4b9b3361

Ответ 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.