2013-12-12 2 views
5

Как я могу заставить Perl сценарий умереть, если что-нибудь написано в STDERR?Умереть, если что-нибудь написано в STDERR?

Такое действие должно быть сделано немедленно, когда такой выход произойдет, или даже до того, чтобы предотвратить это выход ...

+1

Возможный дубликат [Как запустить системную команду и умереть, если что-нибудь написано в STDERR?] (Http://stackoverflow.com/questions/4377967/how-can-i-run-a-system-command -and-die-if-anything-is-written-to-stderr) –

+0

@sputnick - нет системной команды ... –

+0

написан на stderr на что? (т. е. вы хотите включить другие процессы, запущенные вашим процессом? C-библиотечный код, вызванный вашим perl-кодом? perl-предупреждения? Явные отпечатки на stderr?) – ysth

ответ

7

Вот метод, который работает независимо от того, как записывается STDERR (fd 2), даже если это расширение C, которое не использует переменную Perl STDERR, чтобы сделать это. Он даже убивает дочерние процессы, которые пишут в STDERR!

{ 
    pipe(my $r, my $w) 
     or die("Can't create pipe: $!\n"); 
    open(STDERR, '>&', $w) 
     or die("Can't dup pipe: $!\n"); 
    close($r); 
} 

print "abc\n"; 
print "def\n"; 
print STDERR "xxx\n"; 
print "ghi\n"; 
print "jkl\n"; 

$ perl a.pl 
abc 
def 

$ echo $? 
141 

Не работает на Windows. Не работает, если вы добавляете обработчик SIGPIPE.

+0

Интересно! Если я хочу добавить некоторые функции перед выходом, как мне нужно изменить код, пожалуйста? Кроме того, будет ли он работать вместе с «die handler» '$ SIG {__ DIE__} = \ & __ die __;'? –

+1

Нет, это не умирает. Он убит ОС. $ SIG {PIPE} поймает его. – ikegami

+0

И как я могу добавить некоторую функциональность (функцию обратного вызова) к вашему коду, прежде чем он будет убит? –

14

Это не кажется особенно умной идеей, но привязал указатель_на_файл должен работать. В соответствии с справочником perltie:

При привязке STDERR его метод PRINT будет вызываться для выдачи предупреждений и сообщений об ошибках. Эта функция временно отключена во время вызова, что означает, что вы можете использовать warn() внутри PRINT без запуска рекурсивного цикла.

Так что-то вроде этого (взято из станицы руководства, например) должно работать:

package FatalHandle; 

use strict; 
use warnings; 

sub TIEHANDLE { my $i; bless \$i, shift } 

sub PRINT { 
    my $r = shift; 
    die "message to STDERR: ", @_; 
} 

package main; 

tie *STDERR, "FatalHandle"; 

warn "this should be fatal."; 

print "Should never get here."; 

И выходы (с кодом выхода 255):

message to STDERR: this should be fatal. at fh.pl line 17. 
Смежные вопросы