Cada lado de um pipe é executado em um subshell. Um subshell é uma cópia do processo shell original que começa no mesmo estado e depois evolui independentemente¹. As variáveis configuradas no subshell não podem voltar para o shell pai.
No bash, em vez de usar um canal, você pode usar substituição de processo . Isso se comportaria quase identicamente ao pipe, exceto que o loop é executado no shell original e somente tee
é executado em um subshell.
for num in "${numbers[@]}"; do
if ((num > max)); then
echo "old -> new max = $max -> $num"
max=$num
fi
done > >(tee logfile)
echo "Max= $max"
Enquanto eu estava nisso, mudei algumas coisas no seu script:
- Sempre use o dobro aspas em torno de substituições de variáveis, a menos que você saiba por que precisa deixá-las de fora.
- Não use
&&
quando você quer dizerif
. É menos legível e não tem o mesmo comportamento se o status de retorno do comando for usado. - Como estou usando construções específicas do bash, é melhor usar sintaxe aritmética .
Note que existe uma pequena diferença entre a solução pipe e a solução subshell: um comando pipe termina quando ambos os comandos saem, enquanto um comando com uma substituição de processo termina quando o comando principal sai, sem esperar pelo processo no processo substituição. Isso significa que quando o script terminar, o arquivo de log pode não estar totalmente escrito.
Outra abordagem é usar algum outro canal para se comunicar do subshell para o processo de shell original. Você pode usar um arquivo temporário (flexível, mas mais difícil de fazer certo - gravar o arquivo temporário em um diretório apropriado, evitar nome conflitos (use mktemp
), remova-o mesmo em caso de erros). Ou você pode usar outro canal para comunicar o resultado e pegue o resultado em uma substituição de comando.
max=$({ { for … done;
echo "$max" >&4
} | tee logfile >&3; } 4>&1) 3&>1
A saída de tee
vai para o descritor de arquivo 3, que é redirecionado para a saída padrão do script. A saída de echo "$max"
vai para o descritor de arquivo 4, que é redirecionado para a substituição do comando.