Comando POSIX / substituição de processo
_log()( x=0
while [ -e "${TMPDIR:=/tmp}/$$.$((x+=1))" ]
do continue; done &&
mkfifo -- "$TMPDIR/$$.$x" &&
printf %s\n "$TMPDIR/$$.$x" || exit
exec >&- >/dev/null
{ rm -- "$TMPDIR/$$.$x"
logger --priority user."$1" --tag "${0##*/}"
} <"$TMPDIR/$$.$x" &
) <&- </dev/null
Você deve ser capaz de usar isso como:
exec >"$(_log notice)" 2>"$(_log error)"
Aqui está uma versão que faz uso do comando mktemp
:
_log()( p=
mkfifo "${p:=$(mktemp -u)}" &&
printf %s "$p" &&
exec <&- >&- <>/dev/null >&0 &&
{ rm "$p"
logger --priority user."$1" --tag "${0##*/}"
} <"$p" &
)
... que faz o mesmo, exceto pelo fato de permitir que mktemp
selecione o nome do arquivo para você. Isso funciona porque a substituição de processos não é de forma alguma mágica e funciona de maneira muito semelhante à substituição de comandos . Em vez de substituir a expansão pelo valor do comando executado dentro dela, como substituição de comando , a substituição de processo substitui-a pelo nome de um link do sistema de arquivos onde a saída pode ser encontrada .
Embora o shell POSIX não forneça um corolário direto para tal coisa, a emulação é muito simples. Tudo o que você precisa fazer é criar um arquivo, imprimir seu nome no padrão de uma substituição de comando e, no segundo plano, executar seu comando, que será enviado para esse arquivo. Agora você pode apenas redirecionar para o valor dessa expansão - exatamente como faz com a substituição do processo. E assim, o shell POSIX fornece todas as ferramentas que você precisa, é claro - tudo o que é necessário é que você as coloque para usá-las da maneira que mais lhe convier.
Ambas as versões acima garantem que eles destruam o link do sistema de arquivos para os canais que eles criam / usam antes de usá-los. Isso significa que não há limpeza necessária após o fato e, mais importante, seus fluxos estão disponíveis apenas para os processos que inicialmente os abrem - e, portanto, seus links de sistema de arquivos não podem ser usados como um meio de rastrear / seqüestrar sua atividade de log. Deixar seus links fs no sistema de arquivos é uma possível falha de segurança.
Outra maneira é envolvê-lo. Isso pode ser feito dentro do script.
x=${x##*[!0-9]*}
_log(){
logger --priority user."$1" --tag "${0##*/}"
} 2>/dev/null >&2
cd ../"$PPID.$x" 2>/dev/null &&
trap 'rm -rf -- "${TMPDIR:-/tmp}/$PPID.$x"' 0 ||
{ until cd -- "${TMPDIR:=/tmp}/$$.$x"
do mkdir -- "$TMPDIR/$$.$((x+=1))"
done &&
x=$x "$0" "$@" | _log notice
exit
} 2>&1 | _log error
Isso basicamente permitiria que seu script chamasse a si mesmo, se ainda não tivesse, e obteria um diretório de trabalho em temp para inicializar.