%20junto%20com%20a%20sa%C3%ADda%20de%20erro%20(stderr).png)
Existe um script executado via cron com a seguinte linha:
0 * * * * (/var/script.sh | tee -a /var/script.log)
Como reescrevo a entrada do cron para capturar a saída normal stdout
e de erro stderr
? Eles devem ser colocados em arquivos diferentes.
Responder1
cron
Os trabalhos são executados sh
por padrão e, independentemente de sh
ser Bourne, POSIX sh
ou compatível, a sintaxe seria:
0 * * * * /var/script.sh 2>&1 | tee -a /var/script.log
Onde |
faz com que os dois comandos de cada lado sejam executados em paralelo conectados a um tubo com o stdout (fd 1) do esquerdo conectado à extremidade de escrita do tubo e o stdin (fd 0) do direito conectado a o final da leitura.
Adicionando 2>&1
ao esquerdo, temos o fd 2 (stderr) apontando para o mesmo recurso apontado pelo fd 1: a extremidade de escrita do pipe, de modo que tanto a saída normal quanto a de erro de script.sh
irão para o pipe to tee
.
tee
irá gravá-lo em seu stdout (que, no caso de um cron job, é um canal ou arquivo temporário que será usado para enviar um email ao usuário) e em script.log
.
Essa sintaxe também funciona no fish
shell.
Com (t)csh
, zsh
ou bash
(4.0 ou mais recente), você também pode fazer:
SHELL=/bin/zsh # or tcsh, bash ...
0 * * * * /var/script.sh |& tee -a /var/script.log
(onde SHELL=/bin/zsh
é como você diz cron
para usar um shell diferente para interpretar as linhas de comando).
Em fish
, você usaria &|
em vez de |&
.
Com rc
(o sucessor de sh
) ou derivados, a sintaxe é:
SHELL=/bin/rc # or es, akanga
0 * * * * /var/script.sh >[2=1] | tee -a /var/script.log
Com zsh
, você também pode prescindir tee
graças ao seu MULT_IOS
recurso:
SHELL=/bin/zsh
0 * * * * /var/script.sh >&1 2>&2 >>& /var/script.log
O que também teria o benefício de preservar script.sh
o status de saída de e também manteria script.sh
o stderr indo para o stderr original além de script.log
(embora isso não faça muita diferença em um cron job onde stdout e stderr geralmente vão para o mesmo lugar de qualquer maneira).
Alguns shells do tipo Bourne/POSIX ( bash
, ksh93
, zsh
, yash
, mksh
pelo menos) têm uma pipefail
opção que você pode usar para poder relatar erros em qualquer componente de um pipeline:
SHELL=/bin/ksh # or zsh, bash...
0 * * * * set -o pipefail && /var/script.sh 2>&1 | tee -a /var/script.log
Responder2
cron deseja informá-lo sobre qualquer tarefa cron que produza saída. Ele deseja enviar os resultados por e-mail para você. Se você não deseja receber e-mails do cron, certifique-se de que seus trabalhos não produzam saída: não use tee
, apenas redirecione a saída
0 * * * * /var/script.sh >> /var/script.log 2>&1
Observe também que removi os parênteses: não faz sentido executar o script em um subshell.