Come reindirizzare lo stderr in un file

152

Durante l'utilizzo di nohup per inserire un comando da eseguire in background, alcuni contenuti appaiono nel terminale.

cp: error reading ‘/mnt/tt/file.txt’: Input/output error
cp: failed to extend ‘/mnt/tt/file.txt’: Input/output error

Voglio salvare quel contenuto in un file.

    
posta André M. Faria 18.05.2015 - 14:31

2 risposte

249

Esistono due flussi di output principali in Linux (e altri sistemi operativi), output standard (stdout) e standard error (stderr). I messaggi di errore, come quelli che mostri, vengono stampati per errore standard. L'operatore di reindirizzamento classico ( command > file ) reindirizza solo l'output standard, quindi l'errore standard viene ancora visualizzato sul terminale. Per reindirizzare anche lo stderr, hai alcune scelte:

  1. Reindirizza lo stdout in un file e stderr in un altro file:

    command > out 2>error
    
  2. Reindirizza lo stderr su stdout ( &1 ), quindi reindirizza lo stdout in un file:

    command >out 2>&1
    
  3. Reindirizza entrambi su un file:

    command &> out
    

Per ulteriori informazioni sui vari operatori di controllo e reindirizzamento, consulta qui .

    
risposta data terdon 18.05.2015 - 14:50
4

La prima cosa da notare è che ci sono un paio di modi a seconda del tuo scopo e shell, quindi questo richiede una leggera comprensione di molteplici aspetti. Il più tipico è tramite 2> in shell Bourne-like , come dash (che è link simbolico a /bin/sh ) e bash ; la prima è la shell predefinita e conforme a POSIX e l'altra è ciò che la maggior parte degli utenti usa per la sessione interattiva. Differiscono per sintassi e funzionalità, ma fortunatamente per noi il reindirizzamento del flusso di errori funziona allo stesso modo (eccetto &> non standard). Nel caso di csh e dei suoi derivati, il reindirizzamento dello stderr non funziona abbastanza là.

Torniamo a 2> part. Due cose chiave da notare: > significa operatore di reindirizzamento, dove apriamo un file e 2 intero rappresenta il descrittore di file stderr; infatti questo è esattamente lo standard POSIX per il linguaggio shell che definisce il reindirizzamento in sezione 2.7 :

[n]redir-op word

Per semplice reindirizzamento > , il valore intero 1 è implicito per stdout , cioè echo Hello World > /dev/null è uguale a echo Hello World 1>/dev/null . Si noti che l'operatore di numeri interi o di reindirizzamento non può essere quotato, altrimenti la shell non li riconosce come tali e invece tratta come una stringa di testo letterale. Per quanto riguarda la spaziatura, è importante che l'intero sia proprio accanto all'operatore di reindirizzamento, ma il file può essere accanto all'operatore di reindirizzamento o meno, cioè command 2>/dev/null e command 2> /dev/null funzionerà correttamente.

La sintassi alquanto semplificata per il tipico comando nella shell sarebbe

 command [arg1] [arg2]  2> /dev/null

Il trucco qui è che il reindirizzamento può comparire ovunque. Questo è sia 2> command [arg1] che command 2> [arg1] sono validi. Nota che per bash shell, esiste un &> modo per reindirizzare allo stesso tempo sia stdout che stderr, ma ancora una volta - è bash specifico e se stai cercando la portabilità degli script, potrebbe non funzionare. Vedi anche Ubuntu Wiki e Qual è la differenza tra & amp; & gt; e 2 & gt; & amp; 1 .

Nota: L'operatore di reindirizzamento > tronca un file e lo sovrascrive, se il file esiste. Il 2>> può essere usato per aggiungere stderr al file.

Se puoi notare, > è inteso per un singolo comando. Per gli script, possiamo reindirizzare il flusso stderr dell'intero script dall'esterno come in myscript.sh 2> /dev/null oppure possiamo usare exec built-in . L'exec built-in ha il potere di ricablare il flusso per l'intera sessione della shell, per così dire, sia interattivamente che tramite script. Qualcosa come

#!/bin/sh
exec 2> ./my_log_file.txt
stat /etc/non_existing_file

In questo esempio, il file di registro dovrebbe mostrare stat: cannot stat '/etc/non_existing_file': No such file or directory .

Ancora un altro modo è tramite le funzioni. Come kopciuszek annotato nella sua risposta, possiamo scrivere la dichiarazione di funzione con il reindirizzamento già associato, cioè

some_function(){
    command1
    command2
} 2> my_log_file.txt
    
risposta data Sergiy Kolodyazhnyy 03.05.2018 - 09:48

Leggi altre domande sui tag