
Eu tenho esta função extremamente simples no meu script:
# Used for debug tracing.
log()
{
:
echo "log: $1"
}
A ideia é poder personalizar/desativar o registro em um único local. Muito bruto.
Agora quero que meu script não produza absolutamente nenhuma saída quando estiver na configuração de lançamento. A única solução que pensei, mas extremamente suja:
TMPFILE='/tmp/tempfilewithpossiblyuniquename'
cmd 1>"$TMPFILE" 2>"$TMPFILE"
cat "$TMPFILE" | xargs log
rm "$TMPFILE"
paracada comando. Como melhorar isso?
EDIT: quero coletartodossaída para stdout
e stderr
e canalizá-lo através de log()
. Depois log()
pode optar por desconsiderar tudo, registrar em um arquivo, imprimir etc.
Responder1
Primeiramente, essa função registrará apenas a primeira "palavra" de qualquer coisa enviada a ela, já que você usa $1
em vez de "$*"
.
Em segundo lugar, existem (como é frequentemente o caso do POSIX) inúmeras maneiras de fazer esse tipo de coisa. Eu provavelmente escolheria algo como:
log() {
cat - >> "$logfile"
}
do_stuff | log
Mas você também pode:
(
do_stuff
do_more_stuff
) >> "$logfile"
Quanto a suprimir completamente toda a saída - isso é algo que geralmente é melhor deixar para o ambiente de chamada (por exemplo ./thing 1> /dev/null 2> &1
), em vez de bloqueá-lo "no código", por assim dizer. Dito isto:
squashout="true" # comment this out to stop killing output
if ! [[ "true" = "${squashout-false}" ]]; then
# Redirect stdout and stderr to the null device.
exec 1> /dev/null
exec 2> /dev/null
fi
Responder2
Absolutamente nenhuma saída é simples, apenas redirecione o script stdout
e stderr
para /dev/null
:
exec >/dev/null 2>&1
Isso afetará o próprio shell e quaisquer comandos que ele executar posteriormente. Execute isso condicionalmente para escolher para onde a saída será redirecionada.
if [ "$output_to_file" = 1 ]; then
exec > "$outputfilename" 2>&1
elif [ "$output_suppress" = 1 ]; then
exec > /dev/null 2>&1
fi
Observe que a supressãotodosa saída provavelmente não é uma boa ideia. É muito provável que o usuário queiraalgunsnotificação de erros.
Se você insistir em passar a saída pela função (e estiver executando Bash/ksh/Zsh), poderá usar a substituição de processo:
#!/bin/bash
mangle_output() {
# do something smarter here
while read -r line; do
echo "output: $line";
done;
}
# redirect stdout and stderr to the function
exec > >(mangle_output) 2>&1
echo something that produces output
Embora observe que processar a saída com um shell loop não é uma ideia muito boa, no mínimo é lento. Ver:Por que usar um loop de shell para processar texto é considerado uma prática inadequada?. Se tudo que você deseja é redirecionar um arquivo, ou para /dev/null
, basta usar exec
para configurar redirecionamentos.