Come redirect l’output di un intero script della shell all’interno dello script stesso?

È ansible redirect tutto l’output di uno script di shell Bourne da qualche parte, ma con comandi di shell all’interno dello script stesso?

Reindirizzare l’output di un singolo comando è facile, ma voglio qualcosa di più simile a questo:

#!/bin/sh if [ ! -t 0 ]; then # redirect all of my output to a file here fi # rest of script... 

Significato: se lo script viene eseguito in modo non interattivo (ad esempio cron), salva l’output di tutto in un file. Se si esegue in modo interattivo da una shell, lasciare che l’output passi allo stdout come al solito.

Voglio farlo per uno script normalmente eseguito dall’utilità periodica di FreeBSD. Fa parte della corsa giornaliera, che normalmente non mi interessa vedere tutti i giorni via email, quindi non l’ho inviato. Tuttavia, se qualcosa all’interno di questo particolare script fallisce, è importante per me e mi piacerebbe essere in grado di catturare e inviare via e-mail l’output di questa parte dei lavori quotidiani.

Aggiornamento: la risposta di Joshua è azzeccata, ma volevo anche salvare e ripristinare stdout e stderr sull’intero script, il che è fatto in questo modo:

 # save stdout and stderr to file descriptors 3 and 4, then redirect them to "foo" exec 3>&1 4>&2 >foo 2>&1 # ... # restore stdout and stderr exec 1>&3 2>&4 

Affrontare la domanda come aggiornata.

 #...part of script without redirection... { #...part of script with redirection... } > file1 2>file2 # ...and others as appropriate... #...residue of script without redirection... 

Le parentesi ‘{…}’ forniscono un’unità di reindirizzamento I / O. Le parentesi devono apparire dove potrebbe apparire un comando: semplicisticamente, all’inizio di una riga o dopo un punto e virgola. ( Sì, questo può essere reso più preciso, se vuoi cavillare, fammi sapere. )

Hai ragione che puoi preservare lo stdout e lo stderr originali con i reindirizzamenti che hai mostrato, ma di solito è più semplice per le persone che devono mantenere lo script in un secondo momento per capire cosa sta succedendo se si applica il codice reindirizzato come mostrato sopra.

Invia stdout a un file

 exec > file 

con stderr

 exec > file exec 2>&1 

aggiungi sia stdout che stderr al file

 exec >> file exec 2>&1 

Puoi rendere l’intero script una funzione come questa:

 main_function() { do_things_here } 

poi alla fine dello script hai questo:

 if [ -z $TERM ]; then # if not run via terminal, log everything into a log file main_function 2>&1 >> /var/log/my_uber_script.log else # run via terminal, only output to screen main_function fi 

In alternativa, puoi loggare ogni cosa nel logfile ogni volta e comunque inviarlo allo stdout semplicemente facendo:

 # log everything, but also output to stdout main_function 2>&1 | tee -a /var/log/my_uber_script.log 
 [ -t <&0 ] || exec >> test.log 

Per salvare lo stdout e lo stderr originali puoi usare:

 exec [fd number]<&1 exec [fd number]<&2 

Ad esempio, il codice seguente stamperà "walla1" e "walla2" nel file di registro ( a.txt ), "walla3" in stdout, "walla4" in stderr.

 #!/bin/bash exec 5<&1 exec 6<&2 exec 1> ~/a.txt 2>&1 echo "walla1" echo "walla2" >&2 echo "walla3" >&5 echo "walla4" >&6