Quero fazer um loop sobre a saída de um comando sem criar um sub-shell ou usar um arquivo temporário.
A versão inicial do meu script era assim, mas isso não funciona, pois cria um subshell, e o exit
comando finaliza o subshell em vez do script principal necessário. Faz parte de um script muito maior para configurar o roteamento de política e interrompe a execução se detectar uma condição que fará com que o roteamento falhe.
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
Portanto, uma das alternativas sugeridas é usar um comando como este para evitar o subshell.
while read BLAH ; do echo $BLAH; done </root/regularfile
Portanto, parece-me que também devo usar um comando como este para evitar o subshell e ainda obter a saída do programa que desejo.
while read BLAH ; do echo $BLAH; done <(sysctl -a 2>/dev/null | grep '\.rp_filter')
Infelizmente, o uso desse comando resulta nesse erro.
-bash: syntax error near unexpected token `<(sysct ...
Fico realmente confuso, pois isso funciona.
cat <(sysctl -a 2>/dev/null | grep '\.rp_filter')
Eu poderia salvar a saída desse comando em um arquivo temporário e usar o redirecionamento no arquivo temporário, mas queria evitar isso.
Então, por que o redirecionamento está me causando um erro e eu tenho outras opções além de criar um arquivo temporário?
fonte
Respostas:
Você perdeu um
<
. Deveria estar:Pense em
<(sysctl -a 2>/dev/null | grep '\.rp_filter')
ser um arquivo.fonte
<(
no manual do bash (está em "substituição de processo").Para mais algumas alternativas, se alguém voltar aqui ...
Dependendo do shell, você provavelmente pode usar
set -o errexit
para que o shell pai saia quando um comando (incluindo um subshell) sai diferente de zero sem ficar preso em umif
bloco ou em um final&&
ou||
, como emOu, você pode ter o subshell sinalizar o pai usando kill e a variável de ambiente $ PPID, se disponível.
Ou você pode mover o bloco while para uma função e retornar 0/1 (retornar explicitamente 0 após o bloco while) e fazer o seu pipeline como
sysctl | grep | function || exit
. Suponho que você também possa colocar os retornos no bloco inline, mas as funções são suas amigas. ;)fonte