Quiero recorrer la salida de un comando sin crear un sub-shell o usar un archivo temporal.
La versión inicial de mi script se veía así, pero esto no funciona ya que crea una subshell, y el exit
comando termina la subshell en lugar del script principal que se requiere. Es parte de un script mucho más grande para configurar el enrutamiento de políticas, y detiene la ejecución si detecta una condición que hará que el enrutamiento falle.
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
Entonces, una de las alternativas sugeridas es usar un comando como este para evitar la subshell.
while read BLAH ; do echo $BLAH; done </root/regularfile
Entonces, me parece que también debería poder usar un comando como este para evitar la subshell y aún obtener el resultado del programa que quiero.
while read BLAH ; do echo $BLAH; done <(sysctl -a 2>/dev/null | grep '\.rp_filter')
Desafortunadamente, usar ese comando da como resultado este error.
-bash: syntax error near unexpected token `<(sysct ...
Me confundo mucho ya que esto funciona.
cat <(sysctl -a 2>/dev/null | grep '\.rp_filter')
Podría guardar la salida de ese comando en un archivo temporal y usar redireccionar el archivo temporal, pero quería evitar hacerlo.
Entonces, ¿por qué la redirección me da un error, y tengo otras opciones además de crear un archivo temporal?
fuente
Respuestas:
Te perdiste un
<
. Debiera ser:Piensa en
<(sysctl -a 2>/dev/null | grep '\.rp_filter')
ser un archivo.fuente
<(
en el manual de bash (está en "sustitución de proceso").Para algunas alternativas más si alguien viene aquí otra vez ...
Dependiendo del shell, probablemente podría usar
set -o errexit
para que el shell padre salga cuando un comando (incluido un subshell) sale de un estado distinto de cero sin quedar atrapado en unif
bloque o un final&&
o||
, como enO puede hacer que la subshell le señale al padre usando kill y la variable de entorno $ PPID, si está disponible.
O puede mover el bloque while a una función y devolver 0/1 (devolver explícitamente 0 después del bloque while) y simplemente hacer su canalización como
sysctl | grep | function || exit
. Supongo que también podría poner los retornos en el bloque en línea, pero las funciones son su amigo. ;)fuente