如何保存 cron 任务的输出到文件?
cron 输出落盘的正确写法:> 覆盖、>> 追加、2>&1 合并错误流;附按日期分文件、丢弃输出、日志轮转与集中采集建议、FAQ。
在 crontab 命令后面加重定向即可——追加写用 >>,并把错误流合并进去:
* * * * * /bin/backup.sh >> /var/log/backup.log 2>&1
重定向写法速查
| 写法 | 效果 |
|---|---|
> file |
标准输出覆盖写入 |
>> file |
标准输出追加写入(日志场景用这个) |
2>&1 |
把错误流(fd 2)并到标准输出指向的同一文件 |
2>> file |
错误流单独追加到另一文件 |
> /dev/null 2>&1 |
全部丢弃(确认不需要任何输出时才用) |
拆解 >> /var/log/backup.log 2>&1:
>>把标准输出追加到日志文件;2>&1把标准错误也导向同一个文件——顺序不能反,2>&1 >>达不到合并效果。
为什么必须重定向
cron 对任务输出的默认处理是寄本地系统邮件给任务属主。机器没装/没配 MTA 时,输出直接丢失,报错无迹可寻——这就是日志里出现 No MTA installed, discarding output 的原因。显式重定向到文件是最低成本的自救。
进阶写法
按日期分文件(注意 % 要转义):
0 3 * * * /opt/jobs/daily.sh >> /var/log/jobs/daily-$(date +\%Y\%m\%d).log 2>&1
给每条输出带时间戳:
* * * * * /opt/jobs/task.sh 2>&1 | ts '[%Y-%m-%d %H:%M:%S]' >> /var/log/task.log
(ts 来自 moreutils 包。)
别忘了轮转:追加写迟早把磁盘撑满。给 /etc/logrotate.d/ 加一条针对该日志的规则,或用 systemd journal 收敛。
观测云对照
日志落到文件只是第一步——分散在几十台机器上的任务日志,出了事逐台 grep 效率极低。用 DataKit 把这些日志文件统一采集到观测云,全文检索一条查询覆盖所有机器;再对错误关键字、以及"预期时间窗口无日志"的静默失败各配一条监控器告警,cron 监控的两大盲区(报错没人看、不跑没人知道)就都补上了。
常见问题(FAQ)
Q:> 和 >> 用哪个?
A:日志一律用 >> 追加。> 每次执行清空重写,历史全丢,只剩最后一次。
Q:重定向了还是没看到输出?
A:检查三件事:目录是否存在且 cron 用户可写;脚本是否真的往 stdout/stderr 打了东西(有些框架默认写自己的日志文件);% 是否转义。
Q:想让成功和失败写到不同文件?
A:>> success.log 2>> error.log。但实操上更推荐统一写、用日志内容区分级别,检索时过滤即可。