Как я могу открыть() и закрыть() STDERR в Perl?

Привет ,

Я могу закрыть STDERR в Perl, используя;

close(STDERR)

и после выполнения некоторой логики я хочу снова открыть его. Как мне это сделать?

Я пытался

open(STDERR,">&STDERR");

и не работал.

Заранее спасибо.


person Ashika Umanga Umagiliya    schedule 24.11.2009    source источник
comment
ни в коем случае, вы не можете этого сделать. это стандартная действующая система безопасности Unix.   -  person J-16 SDiZ    schedule 24.11.2009
comment
@J-16 SDiZ: безопасность? как же так?   -  person ysth    schedule 24.11.2009
comment
Что делаешь? Возможно, есть лучший способ сделать это, чем закрыть и снова открыть STDERR?   -  person brian d foy    schedule 24.11.2009
comment
Capture::Tiny может быть полезен. Это позволяет вам условно захватывать STDOUT/STDERR и при необходимости обрабатывать его позже metacpan.org/module/Capture:: Крошечный   -  person user1027562    schedule 23.04.2013


Ответы (3)


Почему вы хотите закрыть STDERR?

Вы могли бы отложить это в сторону...

open(FOO, ">/dev/null"); # or ">nul" on Windows
*TEMP = *STDERR;
*STDERR = *FOO;
... then
*STDERR = *TEMP;
person pascal    schedule 24.11.2009
comment
File::Spec-›devnull() вернет соответствующее имя файла - person ysth; 24.11.2009

сначала продублируйте его, а затем продублируйте дубликат, чтобы снова открыть его (проверка ошибок оставлена ​​в качестве упражнения для читателя, хотя работа с ошибками, когда STDERR недоступен, может быть упражнением в разочаровании):

open(my $saveerr, ">&STDERR");
close(STDERR);
open(STDERR, ">&", $saveerr);

Обратите внимание, что когда вы закрываете STDERR, вы освобождаете файловый дескриптор 2; если вы откроете другой файл и он получит файловый дескриптор 2, любые не-Perl-библиотеки, которые вы используете, могут подумать, что другой файл — это stderr.

person ysth    schedule 24.11.2009

STDERR предоставляется родительским процессом. Это не обязательно какой-то обычный файл, поэтому вам лучше держать его открытым, если вы не планируете больше в нем писать. Честно говоря, я бы не стал играться с командной оболочкой tty и заново открыть здесь /dev/pts/XX: это приведет только к неприятностям.

Я предполагаю, что вы можете захотеть сделать так, чтобы какая-то библиотека не производила вывод на STDERR, хотя она была разработана для этого. Для этого вам нужно оставить файл открытым, но перемещать его по списку файловых дескрипторов. Системный вызов new_file_descriptor = dup(old_file_descriptor) делает это в C, после чего dup2(some_fd,2) "активирует" какой-либо файл как stderr и dup2(new_stderr_descriptor,2) "возобновляет" реальный вывод ошибки.

Закрытие одного из дублированных дескрипторов файла должно позволить вам продолжить работу с другим, хотя я ожидаю, что при использовании сокетов здесь будут происходить странные вещи. (остерегайтесь, копайте man-страницы и пишите тестовые случаи, если это необходимо).

О, и, кстати, man-страница perlfunc для open просто показывает вам, как perl делать эти дубликаты, хотя я должен признаться, что не совсем понимаю тонкости этого синтаксиса:

open my $oldout, ">&STDOUT"     or die "Can't dup STDOUT: $!";
open OLDERR,     ">&", \*STDERR or die "Can't dup STDERR: $!";
# ...
person PypeBros    schedule 06.02.2012
comment
заслуга ysth в том, что он предложил dups, но я подумал, что нужно немного больше информации и объяснений. - person PypeBros; 07.02.2012