有一个通过 cron 运行的脚本,其中包含以下行:
0 * * * * (/var/script.sh | tee -a /var/script.log)
如何重写 cron 条目以捕获正常输出stdout
和错误stderr
输出?它们将被放置在不同的文件中。
答案1
cron
作业默认运行sh
,无论是sh
Bourne 还是 POSIXsh
或兼容的,语法都是:
0 * * * * /var/script.sh 2>&1 | tee -a /var/script.log
其中,|
导致任一侧的两个命令与管道连接并行运行,左侧命令的 stdout (fd 1) 插入管道的写入端,右侧命令的 stdin (fd 0) 插入管道的写入端阅读结束。
通过添加2>&1
到左侧,我们使 fd 2 (stderr) 指向与 fd 1 所指出的相同资源:管道的写入端,因此 的正常输出和错误输出都script.sh
将转到管道 to tee
。
tee
会将其写入其标准输出(在 cron 作业的情况下是一个管道或临时文件,将用于向用户发送电子邮件)和script.log
.
该语法在fish
shell 中也适用。
使用(t)csh
,zsh
或bash
(4.0 或更高版本),您还可以执行以下操作:
SHELL=/bin/zsh # or tcsh, bash ...
0 * * * * /var/script.sh |& tee -a /var/script.log
(在哪里SHELL=/bin/zsh
告诉你如何cron
使用不同的 shell 来解释命令行)。
在 中fish
,您可以使用&|
代替|&
.
对于rc
( 的一次后继者sh
) 或导数,语法为:
SHELL=/bin/rc # or es, akanga
0 * * * * /var/script.sh >[2=1] | tee -a /var/script.log
使用zsh
,您也可以不使用它,这tee
要归功于它的MULT_IOS
功能:
SHELL=/bin/zsh
0 * * * * /var/script.sh >&1 2>&2 >>& /var/script.log
这也有利于保留 的script.sh
退出状态,并且还可以将script.sh
的 stderr 保持为原始 stderr script.log
(尽管这在 cron 作业中没有太大区别,其中 stdout 和 stderr 通常会转到无论如何都是同一个地方)。
一些 Bourne/POSIX 之类的 shell(至少bash
)有一个选项,您可以使用它来报告管道任何组件中的错误:ksh93
zsh
yash
mksh
pipefail
SHELL=/bin/ksh # or zsh, bash...
0 * * * * set -o pipefail && /var/script.sh 2>&1 | tee -a /var/script.log
答案2
cron 想要告诉您任何产生输出的 cron 作业。它想通过电子邮件将结果发送给您。如果您不想接收来自 cron 的电子邮件,请确保您的作业不产生输出:不要使用tee
,只需重定向输出
0 * * * * /var/script.sh >> /var/script.log 2>&1
另请注意,我删除了括号:在子 shell 中运行脚本是没有意义的。