一、为什么 cron 更容易出问题¶
定时任务最容易踩坑的地方在于:命令在交互式终端能成功,并不代表放到 cron 里也一定能成功。
原因通常包括:
- 环境变量不完整
- 相对路径失效
- 输出没有重定向
- 特殊字符在 cron 里有额外含义
所以,定时任务除了“能写出来”,更重要的是“能长期稳定运行”。
二、定时任务的几个关键习惯¶
2.1 给任务加注释¶
写定时任务时,建议尽量在上方加注释,说明任务用途。
这样做的好处是:
- 以后自己回头看得懂
- 团队协作时别人也能快速理解
- 出问题时更容易定位任务作用
2.2 尽量用脚本承载业务逻辑¶
原始笔记非常强调:复杂逻辑不要直接堆在 crontab 里,而应尽量封装成脚本。
调试脚本时,可以使用:
$ sh -x backup-conf.sh
或者:
$ bash -x backup-conf.sh
这样可以直接看到脚本执行过程,排错效率会高很多。
2.3 文件和脚本尽量使用绝对路径¶
cron 环境下,相关文件最好写绝对路径,例如:
/server/scripts/backup-etc.sh
2.4 命令也尽量用绝对路径¶
如果在定时任务里直接写命令,也建议尽量写成绝对路径。
例如:
/sbin/ntpdate ntp1.aliyun.com
2.5 一定要处理输出¶
cron 执行时,如果命令或脚本有输出,又没有做重定向,系统通常会把输出通过邮件发给 root,或者在本地邮件目录不断堆积小文件。
常见写法:
# 重定向到空
*/2 * * * * /sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1
# 追加到日志文件
* * * * * echo oldboy >>/tmp/lidao.txt 2>&1
# 备份脚本调试日志
00 01 * * * /bin/sh -x /server/scripts/backup-etc.sh >>/tmp/script.log 2>&1
三、常见故障一:cron 里的 % 有特殊含义¶
在 cron 中,% 不是普通字符,往往会被当作换行或特殊分隔处理。
如果你在定时任务里直接写包含 % 的命令,比如 date +%F,就要特别小心,必要时需要做转义或改写到脚本里再执行。
最稳妥的方式通常是:
- 把复杂命令写进脚本
- 在脚本中使用
date +%F - crontab 只调用脚本
四、常见故障二:命令路径问题¶
4.1 典型现象¶
命令行里手工执行成功,但放进 cron 后提示命令找不到。
4.2 原因¶
cron 的运行环境通常只认识有限的 PATH,常见只包含 /bin、/usr/bin 等基础路径。像 /sbin/ip 这类命令,如果不写绝对路径,cron 可能就找不到。
4.3 解决方法¶
方法一:直接写绝对路径¶
#!/bin/bash
hostname
/sbin/ip a s eth0
方法二:在脚本里重新定义 PATH¶
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
hostname
ip a s eth0
方法三:重新加载系统环境¶
#!/bin/bash
source /etc/profile
hostname
ip a s eth0
五、常见故障三:没有重定向导致邮件堆积¶
5.1 典型现象¶
如果邮件服务开启,系统可能不断提示:
You have new mail in /var/spool/mail/root
如果邮件服务关闭,也可能在本地临时目录或邮件投递目录里不断积累小文件,例如:
/var/spool/postfix/maildrop
5.2 原因¶
cron 执行命令时只要有输出,就可能通过邮件形式发送给 root。
5.3 解决方法¶
把命令输出重定向到空设备或文件:
*/2 * * * * /sbin/ntpdate ntp1.aliyun.com &>/dev/null
* * * * * echo oldboy >>/tmp/lidao.txt 2>&1
00 01 * * * /bin/sh -x /server/scripts/backup-etc.sh &>>/tmp/scripts.log
六、小结¶
cron 最稳的写法,通常都符合这几个原则:
- 有注释
- 逻辑放脚本里
- 路径尽量写绝对路径
- 复杂环境变量自己显式处理
- 所有输出都明确重定向
把这些习惯固定下来,定时任务的稳定性会明显提升,排障也会简单很多。