2011-12-05 15 views
7

Powiedzmy, że chcę uruchomić zewnętrzny program z mojego skryptu z backtickami i jednocześnie chcę uchwycić zarówno STDOUT, jak i STDERR, ale w dwóch różnych zmiennych . Jak mogę to zrobić? Dla istance jeśli uruchomić ten skrypt ...Jak przechwycić STDOUT i STDERR w dwóch różnych zmiennych przy użyciu linków w Perlu

my $cmd = `snmpwalk -v $version -c $community $hostname $oid`; 

... jeśli nie ma błędu wszystko działa dobrze, ale jeśli polecenie zgłosi błąd ten błąd będzie drukowany w wierszu polecenia, a ja nie chcesz, żeby tak się stało. Chcę również uchwycić błąd. Nic nie musi być drukowane na ekranie. Jakieś pomysły?

+2

Czasami warto spojrzeć na [netto -SNMP] (http://search.cpan.org/~dtown/Net-SNMP-v6.0.1/). Dzięki temu będziesz mieć pełną kontrolę błędów i nie musisz się martwić przekierowaniem wyjścia gdzie indziej. –

Odpowiedz

5

W Perl FAQ masz różne opcje w zależności jak chcesz kontynuować:

http://perldoc.perl.org/perlfaq8.html#How-can-I-capture-STDERR-from-an-external-command%3f

+0

* Cięcia i otwarte() odczytują tylko STDOUT twojego polecenia. * Wygląda na to, że nie mogę przechwycić STDERR, muszę użyć Open3, dziękuję dla odpowiedzi btw! – raz3r

+1

podczas gdy ta faq jest poprawna, to jest niepotrzebne skomplikowane i IMO niekompletne. Podczas gdy podstawowy język Perla sprawia, że ​​jest to trudne, istnieją moduły, które mogą pomóc, zobacz moją odpowiedź na przykład przy użyciu ['Capture :: Tiny'] (http://p3rl.org/Capture::Tiny) –

8

Jedynym sposobem, aby to zrobić z backticks jest przekierowanie do pliku wewnątrz polecenia powłoki:

my $cmd = `snmpwalk -v $version -c $community $hostname $oid 2>error.dat`; 

Jeśli chcesz uchwycić STDERR wewnątrz skryptu, trzeba IPC::Open3 zamiast backticks

+0

Nie muszę obsługiwać błędów (ponieważ przypominają mi ostrzeżenia), więc rozwiązanie może być dla mnie odpowiednie. Spróbuję tego teraz :) – raz3r

+0

To nie działa :(error.dat jest pusty i błędy są nadal wywoływane w wierszu poleceń :( – raz3r

+1

Nie wiem, dlaczego to nie powinno działać .Jeśli to tworzy plik , wtedy powłoka działa zgodnie z oczekiwaniami.Może tylko przypuszczać, że snmpwalk wyprowadza błąd przez jakiś inny mechanizm niż drukowanie na STDERR, ale nie wiem co.Miałem powiedzieć, jeśli nie chcesz wyjścia tak czy inaczej, "2>/dev/null", ale jeśli sprawa error.dat nie działa, prawdopodobnie nie, –

11

Nie musisz przechodzić aż do open3, którego IIRC jest tylko wtedy, gdy musisz czytać i pisać do zewnętrznego polecenia, a nawet wtedy są inne metody.

Dla twojego problemu sugeruję użycie Capture::Tiny, który może przechwycić (lub nawet trójkę) STDOUT i STDERR z dowolnego działania wewnątrz jego bloku. Na przykład, na zapytanie:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Capture::Tiny qw/capture/; 

... 

my ($stdout, $stderr) = capture { 
    system ("snmpwalk -v $version -c $community $hostname $oid"); 
}; 

Inny przykład rozważyć ten kod funkcjonującej:

#!/usr/bin/env perl 

use strict; 
use warnings; 

use Capture::Tiny qw/capture/; 

my ($stdout, $stderr) = capture { 
    system ("echo 'hello'"); 
    system ("date"); 
    warn "Arg1!"; 
}; 

print "STDOUT:\n$stdout"; 
print "STDERR:\n$stderr"; 

który po prostu dał mi:

STDOUT: 
hello 
Mon Dec 19 23:59:06 CST 2011 
STDERR: 
Arg1! at ./test.pl line 11. 
Powiązane problemy