bash: Cattura lo stdout su una variabile ma lo visualizza comunque nella console

Ho uno script bash che chiama diversi processi di lunga durata. Voglio catturare l’output di tali chiamate in variabili per motivi di elaborazione. Tuttavia, poiché si tratta di processi a esecuzione prolungata, vorrei che l’output delle chiamate rsync venisse visualizzato nella console in tempo reale e non dopo il fatto.

A tal fine, ho trovato un modo per farlo, ma si basa sull’output del testo su / dev / stderr. Ritengo che l’output di / dev / stderr non sia un buon modo di fare le cose.

VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr) VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr) VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr) 

Nell’esempio sopra, sto chiamando rsync alcune volte e voglio vedere i nomi dei file mentre vengono elaborati, ma alla fine voglio ancora l’output in una variabile perché lo analizzerò in un secondo momento.

Esiste un modo “più pulito” per realizzare questo?

Se fa la differenza, sto usando Ubuntu 12.04, bash 4.2.24.

Duplica e 1 nella tua shell (nel mio esempio di 5) e usa & 5 nella subshell (in modo che tu scriva su stdout (& 1) della shell madre):

 exec 5>&1 FF=$(echo aaa|tee >(cat - >&5)) echo $FF 

Stamperà aaa due volte, una a causa dell’eco nella subshell e la seconda volta stamperà il valore della variabile.

Nel tuo codice:

 exec 5>&1 VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5)) # use the value of VAR1 

La risposta di Op De Cirkel ha l’idea giusta. Può essere semplificato ancora di più (evitando l’uso del cat ):

 exec 5>&1 FF=$(echo aaa|tee /dev/fd/5) echo $FF 

Ecco un esempio che cattura sia stderr sia il codice di uscita del comando. Questo sta prendendo spunto dalla risposta di Russell Davis.

 exec 5>&1 FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]}) exit_code=$? echo "$FF" echo "Exit Code: $exit_code" 

Se la cartella /taco/ esiste, questo ne catturerà il contenuto. Se la cartella non esiste, acquisirà un messaggio di errore e il codice di uscita sarà 2.

Se ometti 2>&1 verrà catturato solo lo stdout .

È ansible utilizzare più di tre descrittori di file. Prova qui:

http://tldp.org/LDP/abs/html/io-redirection.html

“Ad ogni file aperto viene assegnato un descrittore di file. [2] I descrittori di file per stdin, stdout e stderr sono rispettivamente 0, 1 e 2. Per l’apertura di file aggiuntivi rimangono dei descrittori da 3 a 9. A volte è utile assegnare uno di questi descrittori di file aggiuntivi a stdin, stdout o stderr come collegamento duplicato temporaneo. ”

Il punto è se vale la pena rendere la sceneggiatura più complicata solo per ottenere questo risultato. In realtà non è veramente sbagliato, nel modo in cui lo fai.