Ho riscontrato un problema nel verificare se un determinato comando in una catena di comando multi-pipe ha generato un errore. Di solito questo non è difficile da controllare, ma né set -o pipefail
né il controllo ${PIPESTATUS[@]}
funziona nel mio caso. La configurazione è la seguente:Bash: verifica dello stato di uscita della catena di comando multi-pipe
cmd="$snmpcmd $snmpargs $agent $oid | grep <grepoptions> for_stuff | cut -d',' f$fields | sed 's/ubstitute/some_other_stuff/g'"
Nota 1: il comando è stato testato a fondo e funziona perfettamente.
Ora, voglio memorizzare l'output di tale comando in un array chiamato procdata
. Così, ho fatto:
declare -a procdata
procdata=($(eval $cmd))
Nota-2: eval
è necessario perché altrimenti $snmpcmd
tiri su con un errore invalid option -- <grepoption>
che non ha senso, perché <grepoption>
non è un'opzione $snmpcmd
ovviamente. A questo punto considero questo un bug con $snmpcmd
ma questo è un altro spettacolo ...
Se si verifica un errore, procdata
sarà vuoto. Tuttavia, potrebbe essere vuoto per due diversi motivi: o perché si è verificato un errore durante l'esecuzione dello $snmpcmd
(ad es. Timeout) o perché grep
non è riuscito a trovare ciò che stava cercando. Il problema è che devo essere in grado di distinguere tra questi due casi e gestirli separatamente.
Pertanto, set -o pipefail
non è un'opzione in quanto propagherà qualsiasi errore e non è possibile distinguere quale parte della pipe ha avuto esito negativo. D'altra parte echo ${PIPESTATUS[@]}
è sempre 0
dopo il procdata=($(eval $cmd))
anche se ho molti tubi!?. Tuttavia, se eseguo l'intero comando direttamente al prompt e richiama immediatamente echo ${PIPESTATUS[@]}
, restituisce lo stato di uscita di tutte le pipe correttamente.
So che potrei associare il flusso err a stdout ma dovrei usare metodi euristici per verificare se gli elementi in procdata
sono validi o messaggi di errore e corro il rischio di ottenere falsi positivi. Potrei anche eseguire il pipe stdout su /dev/null
e catturare solo il flusso di errori e controllare se ${#procdata[@]} -eq 0
. Ma dovrei ripetere la chiamata per ottenere i dati effettivi e l'intero comando è costoso in termini di tempo (circa 3-5s). Non vorrei chiamarlo due volte. O potrei usare un file temporaneo per scrivere errori, ma preferirei farlo senza il sovraccarico di creare/cancellare file.
Qualche idea su come posso farlo funzionare in bash?
Grazie
PS:
$ echo $BASH_VERSION
4.2.37(1)-release
ho avuto lo stesso pensiero. Sfortunatamente non funziona, ma non sono sicuro del perché. Inserisco i comandi esatti perché potrei non vedere l'ovvio: – user3040975
'local cmdargs =" - CHf, -m $ mibs -v $ snmpver -c $ community $ agent "; local procdatacmd = "$ tblcmd $ cmdargs $ proc_table"; procdatacmd + = "| cut -d ',' -f $ fields | grep -we -e | sort | uniq -c | sed 's/^ * \ | \" // g; s//,/g' ; echo $ {PIPESTATUS [@]} "' Allora faccio: 'declare -a procdata = ($ (testa -n -1 <<< $ procdatacmd)). L'output è vuoto ... solo nulla e è attivo e funzionante sull'agente. Cosa ... –
user3040975
@ user3040975 Sembra che non ci sia _running_ qualsiasi comando nella riga sopra. – devnull