2011-12-05 1 views
7

Diciamo che voglio eseguire un programma esterno dal mio script con i backtick e allo stesso tempo voglio catturare sia STDOUT che STDERR ma in due variabili diverse . Come lo posso fare? Per istance se corro questo script ...Come catturare STDOUT e STDERR in due variabili diverse usando Backtick in Perl

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

... se non v'è tutto l'errore funziona bene, ma se il comando genera un errore questo errore verrà stampato sulla riga di comando e io no voglio che ciò accada. Voglio catturare anche l'errore. Nulla deve essere stampato sullo schermo. Qualche idea?

+2

Si potrebbe voler dare un'occhiata a [Net -SNMP] (http://search.cpan.org/~dtown/Net-SNMP-v6.0.1/). Con questo avrai pieno controllo degli errori e non dovrai preoccuparti di reindirizzare l'output da qualche altra parte. –

risposta

5

Nel Perl FAQ si hanno diverse opzioni a seconda come si vuole procedere:

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

+0

* Backtick e open() leggono solo lo STDOUT del tuo comando. * Così sembra che non riesca a catturare STDERR, devo usare Open3, grazie per la risposta btw! – raz3r

+1

mentre questa faq è corretta, è unnec Essenzialmente complicato e IMO incompleto. Mentre il linguaggio Perl di base rende questo difficile, ci sono dei moduli che possono aiutare, vedere la mia risposta per esempi usando ['Capture :: Tiny'] (http://p3rl.org/Capture::Tiny) –

8

L'unico modo per fare questo con apici inversi è quello di reindirizzare a un file all'interno del comando della shell:

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

Se si desidera catturare lo STDERR all'interno dello script, è necessario IPC::Open3 invece di apici inversi

+0

Beh, non devo gestire gli errori (perché sono più come avvertimenti per me) in modo che la soluzione possa essere adatta a me. Lo sto provando in questo momento :) – raz3r

+0

Non funziona :(error.dat è vuoto e gli errori continuano a essere generati dalla riga di comando :( – raz3r

+1

Non so perché non dovrebbe funzionare.Se sta creando il file , quindi la shell funziona come previsto. Posso solo supporre che snmpwalk stia emettendo l'errore da qualche altro meccanismo rispetto alla stampa su STDERR, ma non so cosa, stavo per dire, se non vuoi che l'output comunque, '2>/dev/null', ma se il caso error.dat non funziona, probabilmente non lo sarà, –

11

Non è necessario andare fino a open3, che IIRC è solo per quando è necessario leggere e scrivere su un comando esterno, e anche in questo caso ci sono altri metodi.

Per il tuo problema ti suggerisco di usare Capture::Tiny, che può catturare (o anche tee) lo STDOUT e lo STDERR da qualsiasi cosa venga eseguito all'interno del suo blocco. Ad esempio, secondo la vostra domanda:

#!/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"); 
}; 

Per un altro esempio si consideri questo codice funzionamento:

#!/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"; 

che mi ha dato:

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