如何重定向cron脚本的完整输出

5

我有一个简单的cronjob,每天在18:35运行:

05 18 * * * ~/job.sh 2>&1 >> ~/job.log

所以 ~/job.sh 的输出应该被写入 ~/job.log。在 job.sh 中,有一些 echo 命令和一些执行的 Python 脚本,例如:

echo 'doing xyz'
python doXYZ.py

现在,无论python脚本产生什么输出,它们都没有写入到~/job.log中。我只能在~/job.log中看到echo文本。如何将shell脚本的完整输出重定向到~/job.log?

4个回答

17

Arkaitz提供了最简单的解决方案。然而,要查看您的代码片段有什么问题,我们需要查看bash手册:

请注意,重定向的顺序是有意义的。例如,以下命令

  ls > dirlist 2>&1

将标准输出和标准错误都定向到文件dirlist,同时执行该命令。

 ls 2>&1 > dirlist

该命令将标准输出重定向到文件dirlist,因为在将标准输出重定向到dirlist之前,标准错误已经从标准输出中复制。

显然,输出重定向只会重定向到另一个流的目标,而不是另一个流本身。当Bash解析您的命令行时,它会遇到2>&1子句,并将stderr重定向到stdout的目标,这时候目标仍然是控制台(或连接到的stdout的其他设备),只有在此之后,stdout才会被重定向。

所以你真正想要的是:

05 18 * * * ~/job.sh >>~/job.log 2>&1

@musicinmybrain:不是很清楚,我几天前也遇到了完全相同的问题。 :-) - wds

4
你尝试过这样做吗? ~/job.sh &>> ~/job.log ?


&>>完全不产生任何输出。 &>会产生正确的输出。但是,它不会追加,而是覆盖!我该如何让它将新输出附加到旧内容上? - pruefsumme
它确实将内容追加到文件中。 - Hani Gotc

2

您需要重定向Python脚本的输出。《学习Python第二版》推荐以下方法:

import sys
sys.stdout = open('log.txt', 'a')   # Redirects output to file
...
print x, y, x                       # shows up in log.txt

并继续说道:

“在这里,我们将sys.stdout重置为以追加模式打开的手动打开的输出文件对象。重置后,程序中任何地方的print语句都会将其文本写入文件log.txt的末尾,而不是原始输出流。”


1
这对于Python脚本来说是可行的,但不太优雅,因为需要在Python脚本和cronjob中都指定日志文件名。此外,如果我需要重定向“job.sh”中的其他命令的输出(比如说其中有一个“git commit -a -m 'auto-commit'”),这种方法就无法帮助了。 - pruefsumme

1

我非常确定这在一般情况下应该可以工作。当你使用shell重定向时,stdout文件描述符会被操作系统更改。

然而,如果你的Python脚本直接向屏幕写入(可能通过打开/dev/tty),它将不会被捕获到log.txt中。是这种情况吗?即使对于一个只执行简单python程序的情况,它也会失败吗?

print "Hello"

?


是的,即使是一个仅包含此打印行的简单Python脚本也不会写入日志。问题在于重定向的顺序(请参见wds的答案)。 - pruefsumme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接