Invia l'output bash -x al file di log senza interrompere l'output standard


12

C'è un modo per inviare le informazioni visualizzate eseguendo uno script bash con l'opzione -x in un file, senza cambiare l'output standard visto da un utente che esegue lo script?

Questa è una funzione di debug che vorrei implementare in uno script bash che usiamo che cambia frequentemente.

Molto apprezzato.

Risposte:


21

L'output di -x va a stderr, non a stdout. Ma anche questo può essere un problema: molti script avranno dipendenze funzionali dal contenuto di stderr, e il suo tipo di disordine ha i flussi di debug e stderr mescolati insieme in alcuni casi.

Le versioni di Bash> 4.1 offrono una soluzione diversa: la variabile di ambiente BASH_XTRACEFD consente di specificare un descrittore di file che verrà utilizzato per inviare il flusso di debug. Questo può essere un file o pipe o qualsiasi altra bontà unix-y che ti piace.

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

Con un po 'più di confusione, puoi fare altre cose - come fare una' tee 'sui flussi stdout e / o stdin, e interfogliare quelli con l'output di debug, quindi il tuo registro è più completo. Per maggiori dettagli al riguardo, consultare /programming/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself .

Il grande vantaggio di questo approccio rispetto alle alternative è che non stai rischiando modifiche al comportamento del tuo script iniettando l'output di debug in stdout o stderr.


Vedi anche qui su come trovare un descrittore di file non utilizzato per il file.
jarno,

È necessario chiudere il descrittore di file (es. Linea exec 19>&-)? Nella mia esperienza, si chiude automaticamente quando termina lo script.
jarno,

1
Il codice mostrato sopra non presuppone che tu stia eseguendo uno script, o quanto tempo potrebbe essere lo script, ecc. È vero che se fai semplicemente quello che fa questo snippet e lo metti in uno script, l'handle del file sarà essere chiuso solo perché l'intera shell scompare alla fine della sceneggiatura. Quindi, in quel caso d'uso, non è strettamente necessario chiudere la maniglia. Ma in generale quando si codifica contro una risorsa, è una buona pratica chiudere ciò che si è aperto, perché quindi il codice può essere utilizzato in un contesto più ampio in cui è più probabile che le pulizie siano importanti.
Stabledog,

Perché esporti BASH_XTRACEFD? Perché non solo impostare un valore per questo?
jarno,

In ogni caso, un modo alternativo per chiudere il descrittore di file è impostare un nuovo valore (ad es. Null) per BASH_XTRACEFD o annullarlo.
jarno,

4

set -xnon invia nulla all'output standard, quindi non ci sono problemi. Quello che fa è scrivere nell'errore standard, che va alla console di default.

Quello che vuoi fare è reindirizzare stdout su un altro file, in questo modo:

/bin/sh -x /my/script/file 2>/my/log/file

1

Vedere man tee.

Lo esegui come tee commandname filenamee mostrerà l'output dei comandi stdoute lo scriverà anche in filename.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.