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

5 投票
4 回答
7758 浏览
提问于 2025-04-15 16:55

我有一个简单的定时任务,每天在18:35运行:

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

这个定时任务的输出应该写入到 ~/job.log 文件中。在 job.sh 这个脚本里,有一些 echo 命令,还有几个 Python 脚本会被执行,比如:

echo 'doing xyz'
python doXYZ.py

现在,不管这些 Python 脚本产生什么输出,它们都没有写入到 ~/job.log 文件里。我只在 ~/job.log 里看到了 echo 的文本。请问我该怎么做才能把整个 shell 脚本的输出都重定向到 ~/job.log 呢?

4 个回答

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 的末尾,而不是写到原来的输出流。”

4

你试过用 ~/job.sh &>> ~/job.log 吗?

17

Arkaitz 提出了最简单的解决方案。不过,要找出你代码片段的问题,我们需要看看 bash 的手册:

注意,重定向的顺序是很重要的。例如,命令

  ls > dirlist 2>&1

会把标准输出和标准错误都导向文件 dirlist,而命令

 ls 2>&1 > dirlist

只会把标准输出导向文件 dirlist,因为标准错误在标准输出被重定向到 dirlist 之前就已经被复制了。

所以显然,输出重定向只是把内容导向另一个流的目标,而不是直接导向那个流本身。当 bash 解析你的命令行时,会遇到 2>&1 这个部分,并把 stderr 重定向到 stdout 的目标,而此时的目标仍然是控制台(或者是和 cronstdout 连接的其他地方)。只有在这之后,stdout 才会被重定向。

所以你真正想要的是:

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

撰写回答