Linux crontab定时任务不执行常见原因与排查

前言

配置好了 crontab 定时任务,时间也写对了,但到点就是不执行?这是很多新手都会遇到的坑。crontab 不执行的原因五花八门,从最基础的语法错误到环境变量问题,再到 SELinux 拦截,排查起来很费时间。本文把常见的 crontab 不执行原因都整理出来,按排查顺序一步步来,基本能解决 90% 的问题。

第一步:确认 crond 服务是否运行

最基础也是最容易忽略的——定时任务服务本身有没有启动。

systemctl status crond

如果显示 inactive (dead),说明服务没启动,先启动它:

systemctl start crond
systemctl enable crond

CentOS7 上定时服务叫 crond,Debian/Ubuntu 上叫 cron,别搞混了。

第二步:检查 crontab 语法是否正确

1. 查看当前用户的定时任务

crontab -l

2. crontab 时间格式

* * * * * 命令
- - - - -
| | | | |
| | | | ----- 星期几 (0 - 7) (0和7都是周日)
| | | ------- 月份 (1 - 12)
| | --------- 日期 (1 - 31)
| ----------- 小时 (0 - 23)
------------- 分钟 (0 - 59)

3. 常见语法错误

错误1:分钟写在最前面

# 错误:每天9点执行(错的)
0 9 * * * /root/backup.sh

# 正确:每天9点执行
0 9 * * * /root/backup.sh

等等,这个其实是对的。真正容易错的是:

错误2:命令路径用了相对路径

# 错误:crontab 里找不到 mysql 命令
0 9 * * * mysql -u root -p123456 dbname < /root/backup.sql

# 正确:用绝对路径
0 9 * * * /usr/bin/mysql -u root -p123456 dbname < /root/backup.sql

crontab 的环境变量和你手动登录时不一样! 它的 PATH 很精简,很多命令找不到。所以要么用绝对路径,要么在脚本里先 source 环境变量。

第三步:检查脚本本身有没有执行权限

很多人写了脚本,但忘了加执行权限:

ls -l /root/backup.sh

如果没有 x 权限,加上:

chmod +x /root/backup.sh

第四步:检查脚本内容有没有问题

1. 脚本里用了相对路径

# 错误:相对路径在 crontab 里会出问题
cd /var/www/html
tar -zcf backup.tar.gz .

# 正确:用绝对路径
cd /var/www/html
tar -zcf /root/backup.tar.gz .

2. 脚本里用了交互式命令

比如 read、ssh 需要交互输入的命令,在 crontab 里是跑不了的,因为没有终端。

3. 脚本开头没写 shebang

# 正确的 shebang
#!/bin/bash

如果脚本没有 shebang,或者 shebang 写错了,执行就会失败。

第五步:检查日志

crontab 的执行日志默认在 /var/log/cron 里:

tail -100 /var/log/cron

如果日志里显示任务被执行了,但结果不对,那就是脚本本身的问题。

如果日志里压根没有这个任务的记录,那就是 crontab 服务本身的问题或者任务格式不对。

第六步:检查环境变量问题

这是最隐蔽的坑。你手动跑脚本没问题,但 crontab 里就是不行,十有八九是环境变量的问题。

排查方法:在脚本开头加上环境变量

#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

或者直接在 crontab 里指定:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
0 9 * * * /root/backup.sh

第七步:检查 SELinux 是不是拦截了

如果 SELinux 开着,可能会拦截 crontab 的操作。查看日志:

tail -100 /var/log/audit/audit.log | grep crontab

如果看到 denied 字样,就是 SELinux 拦截了。

第八步:检查邮箱通知

crontab 默认会把执行结果(包括错误信息)发到执行用户的邮箱里:

mail

或者看 /var/spool/mail/root 文件:

tail -100 /var/spool/mail/root

这里面通常会有具体的错误信息,是排查的好帮手。

常见坑

坑1:环境变量缺失

这是最常见的坑。你手动跑脚本能成,crontab 里就不行,因为 crontab 的环境变量和你登录 shell 的不一样。

解决: 在脚本开头加上 export PATH=...,或者所有命令都用绝对路径。

坑2:脚本没有执行权限

写完脚本忘了 chmod +x,crontab 当然跑不了。

坑3:重定向丢了

crontab 默认会把输出发到邮箱,如果你不想收邮件,可以重定向:

0 9 * * * /root/backup.sh > /dev/null 2>&1

> /dev/null 是丢弃标准输出,2>&1 是把错误输出也重定向到标准输出。

坑4:时间格式写错了

比如把 * * * * * 写成了 * * * *,少了一个字段,直接就不执行。

坑5:用户写错了

你用 root 用户写的 crontab,但实际是别的用户需要跑,当然不执行。用 crontab -u 用户名 -l 查看对应用户的任务。

总结

crontab 不执行的排查顺序:

  1. 先确认 crond 服务启动了没
  2. 检查 crontab 语法格式对不对
  3. 脚本有没有执行权限
  4. 脚本里的命令是不是都用了绝对路径
  5. 看 /var/log/cron 日志有没有执行记录
  6. 看 /var/spool/mail/root 有没有错误信息
  7. 检查 SELinux 是不是拦截了

按这个顺序排查,基本都能找到原因。记住 crontab 的环境变量和你手动登录时不一样,所有命令都用绝对路径,能避免 80% 的问题。

遇到问题加QQ23979811 协助处理


emer 发布于  2026-10-5 07:27