Jak przechwycić stderr, stdout i kod wyjścia jednocześnie w Perlu?
Czy jest możliwe uruchomienie zewnętrznego procesu z Perla, przechwycenie jego stderr, stdout i kodu zakończenia procesu?
Wydaje mi się, że jestem w stanie wykonać ich kombinacje, np. użyć backticks, aby uzyskać stdout, IPC::Open3, aby przechwycić wyjścia, i system (), aby uzyskać kody wyjścia.
Jak przechwycić stderr, stdout i kod wyjścia na raz?
6 answers
Jeśli ponownie przeczytasz dokumentację IPC:: Open3, zobaczysz notatkę, którą powinieneś wywołać waitpid , Aby pobrać proces potomny. Gdy to zrobisz, status powinien być dostępny w $?
. Wartość wyjściowa to $? >> 8
. Zobacz też
$?
w perldoc perlvar .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-30 17:20:13
(Update : zaktualizowałem API dla IO:: CaptureOutput, aby było to jeszcze łatwiejsze.)
Można to zrobić na kilka sposobów. Oto jedna z opcji, używając modułu IO::CaptureOutput :use IO::CaptureOutput qw/capture_exec/;
my ($stdout, $stderr, $success, $exit_code) = capture_exec( @cmd );
Jest to funkcja capture_exec (), ale IO::CaptureOutput ma również bardziej ogólną funkcję capture (), która może być użyta do przechwytywania wyjścia Perla lub wyjścia z zewnętrznych programów. Więc jeśli jakiś moduł Perla użyje jakiegoś zewnętrznego programu, nadal otrzymujesz wyjście.
Oznacza to również, że musisz pamiętać tylko jedno podejście do przechwytywania STDOUT i STDERR (lub ich scalania) zamiast używać IPC::Open3 dla zewnętrznych programów i innych modułów do przechwytywania wyjścia Perla.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 21:48:13
Jeśli nie chcesz zawartości STDERR, to polecenie capture() z modułu IPC::System::Simple jest prawie dokładnie tym, czego szukasz:
use IPC::System::Simple qw(capture system $EXITVAL);
my $output = capture($cmd, @args);
my $exit_value = $EXITVAL;
Można użyć metody capture () z pojedynczym argumentem do wywołania powłoki lub z wieloma argumentami, aby niezawodnie uniknąć powłoki. Istnieje również funkcja capturex (), która nigdy nie wywołuje powłoki, nawet z jednym argumentem.
W przeciwieństwie do wbudowanych poleceń systemu i backticks w Perlu, IPC:: System:: Simple zwraca pełną 32-bitową wartość wyjściową pod Okna. Rzuca również szczegółowy wyjątek, jeśli polecenie nie może zostać uruchomione, umiera na sygnał lub zwraca nieoczekiwaną wartość zakończenia. Oznacza to, że w przypadku wielu programów, zamiast samemu sprawdzać wartości wyjściowe, możesz polegać na IPC:: System:: proste do wykonania ciężkiej pracy dla Ciebie:
use IPC::System::Simple qw(system capture $EXIT_ANY);
system( [0,1], "frobincate", @files); # Must return exitval 0 or 1
my @lines = capture($EXIT_ANY, "baznicate", @files); # Any exitval is OK.
foreach my $record (@lines) {
system( [0, 32], "barnicate", $record); # Must return exitval 0 or 32
}
IPC:: System:: Simple jest czystym Perlem, nie ma zależności i działa zarówno na systemach Unix, jak i Windows. Niestety, nie zapewnia sposobu przechwytywania STDERR, więc może nie być odpowiedni dla wszystkich Twoich potrzeb.
IPC:: Run3 zapewnia czysty i łatwy interfejs do ponownego instalowania wszystkich trzech popularnych filehandle, ale niestety nie sprawdza, czy polecenie powiodło się, więc musisz sprawdzić $? ręcznie, co wcale nie jest zabawne. Udostępnienie publicznego interfejsu do kontroli $? czy jest coś co jest na mojej liście zadań dla IPC::System::proste, skoro sprawdzam $? w sposób wieloplatformowy nie jest zadaniem, którego nikomu bym nie życzył.
Istnieją inne moduły w przestrzeni nazw IPC:: , która może również zapewnić Ci pomoc. YMMV.
Wszystkiego najlepszego,
Paweł
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 00:57:54
Istnieją trzy podstawowe sposoby uruchamiania zewnętrznych poleceń:
system $cmd; # using system()
$output = `$cmd`; # using backticks (``)
open (PIPE, "cmd |"); # using open()
Z system()
, zarówno STDOUT
, jak i STDERR pójdą w to samo miejsce co skrypt STDOUT
i STDERR,
, chyba że polecenie system()
przekieruje je. Backticks i open()
odczytują tylko STDOUT
Twojego polecenia.
Możesz również wywołać coś podobnego z open, aby przekierować zarówno STDOUT
, jak i STDERR
.
open(PIPE, "cmd 2>&1 |");
Kod powrotu jest zawsze przechowywany w $?
, Jak zauważył @Michael Carman.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:47
Jeśli robisz się naprawdę skomplikowany, możesz spróbować Expect.pm. ale to prawdopodobnie przesada, jeśli nie musisz również zarządzać wysyłaniem danych wejściowych do procesu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-21 03:15:38
Uznałem IPC: run3 za bardzo pomocny. Możesz przesłać wszystkie dziecięce rury do glob lub zmiennej; bardzo łatwo! A kod zakończenia będzie przechowywany w $?.
Poniżej, jak chwyciłem stderr, który wiedziałem, że będzie numerem. Cmd wyprowadza transformacje informatyczne na stdout (które przesyłam do pliku w args używając >) i raportuje ile transformacji na STDERR.
use IPC::Run3
my $number;
my $run = run3("cmd arg1 arg2 >output_file",\undef, \undef, \$number);
die "Command failed: $!" unless ($run && $? == 0);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-25 17:21:40