Scorrere l'output di un comando in bash senza una subshell


9

Voglio passare in rassegna l'output di un comando senza creare una sotto-shell o utilizzando un file temporaneo.

La versione iniziale del mio script era simile a questa, ma non funziona poiché crea una subshell e il exitcomando termina la subshell anziché lo script principale richiesto. Fa parte di uno script molto più grande per configurare il routing delle politiche e interrompe l'esecuzione se rileva una condizione che causerà il fallimento del routing.

sysctl -a 2>/dev/null | grep '\.rp_filter' | while read -r -a RPSTAT ; do

  if [[ "0" != "${RPSTAT[2]}" ]] ; then
    echo >&2 "RP Filter must be disabled on all interfaces!"
    echo >&2 "The RP filter feature is incompatible with policy routing"
    exit 1
  fi
done

Quindi una delle alternative suggerite è quella di usare un comando come questo per evitare la subshell.

while read BLAH ; do echo $BLAH; done </root/regularfile

Quindi mi sembra che dovrei anche essere in grado di utilizzare un comando come questo per evitare la subshell e ottenere comunque l'output dal programma che desidero.

while read BLAH ; do echo $BLAH; done <(sysctl -a 2>/dev/null | grep '\.rp_filter')

Sfortunatamente, l'utilizzo di quel comando provoca questo errore.

-bash: syntax error near unexpected token `<(sysct ...

Mi confondo molto perché funziona.

cat <(sysctl -a 2>/dev/null | grep '\.rp_filter')

Potrei salvare l'output di quel comando in un file temporaneo e utilizzare il reindirizzamento sul file temporaneo, ma volevo evitare di farlo.

Quindi perché il reindirizzamento mi sta dando un errore e ho altre opzioni oltre alla creazione di un file temporaneo?


Risposte:


13

Ti sei perso a <. Dovrebbe essere:

while read BLAH ; do echo $BLAH; done < <(sysctl -a 2>/dev/null | grep '\.rp_filter')

Pensa di <(sysctl -a 2>/dev/null | grep '\.rp_filter')essere un file.


Molte grazie. Solo per la mia modifica, puoi indicarmi una pagina man, una guida o una pagina web che documenta questo? Non sono riuscito a convincere Google a indicarmi qualcosa di utile mentre cercavo di cercarlo.
Zoredache,

2
Google "sostituzione del processo". ad es. tldp.org/LDP/abs/html/abs-guide.html#PROCESS-SUB
dogbane

Va notato che la sostituzione <() utilizza descrittori di file e su alcuni sistemi operativi creerà e utilizzerà in modo trasparente file temporanei.
ewindisch,

@Zoredache: cerca semplicemente <(nel manuale di bash (è in "sostituzione del processo").
Gilles 'SO- smetti di essere malvagio' il

@ewindisch, se uno strumento crea in modo trasparente un tempfile, non volevo crearne uno manualmente, quando ero abbastanza sicuro di non averne bisogno.
Zoredache,

0

Per qualche altra alternativa se qualcuno viene di nuovo qui ...

A seconda della shell, si potrebbe probabilmente usare set -o errexitl'uscita della shell genitore quando un comando (inclusa una subshell) esce da zero senza essere intrappolato in un ifblocco o un trailing &&o ||, come in

/bin/false || echo "ignoring error"

In alternativa, è possibile che la subshell segnali il padre utilizzando kill e la variabile di ambiente $ PPID, se disponibile.

Oppure potresti spostare il blocco while in una funzione e restituire 0/1 (restituire esplicitamente 0 dopo il blocco while) e fare semplicemente la tua pipeline come sysctl | grep | function || exit. Suppongo che potresti inserire anche i ritorni nel blocco inline, ma le funzioni sono tuo amico. ;)

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.