IT

Linux crontab 不执行?按这五步排查准能找到原因

AI智能摘要

crontab 不执行,先别怀疑人生。查服务状态、看语法、重点盯环境变量和路径,再翻日志确认有没有触发。大部分问题出在 PATH 太干净或命令没写绝对路径,日志里一看就明白。

crontab 写了任务,时间到了却什么都没发生——这是运维里很常见的问题。原因通常不是 cron 服务坏了,而是环境、路径、权限或语法出了偏差。下面按从外到内的顺序,一步步排查,基本能覆盖 90% 的情况。

先确认 cron 服务本身在运行

如果 cron 守护进程没启动,所有任务都不会执行。不同发行版的服务名不一样:

# Debian/Ubuntu
systemctl status cron

# CentOS/RHEL
systemctl status crond

如果状态不是 active (running),先启动并设为开机自启:

sudo systemctl start cron   # 或 crond
sudo systemctl enable cron

另外,有些容器环境(如 Alpine)默认不装 cron,需要手动安装并启动。

检查 crontab 语法和用户

语法错误会导致整行被忽略,而且 cron 不会报错。常见坑:

  • 五个时间字段顺序错:分 时 日 月 周
  • 命令后面没加 >> /var/log/xxx.log 2>&1,输出被丢弃,看起来像没执行
  • 用 % 时没转义,cron 会把 % 当成换行符

用 crontab -l 查看当前用户的任务;如果是系统级任务,检查 /etc/crontab 和 /etc/cron.d/ 下的文件。注意系统级 crontab 多一个用户字段,别和用户级搞混。

环境变量和路径是最大元凶

cron 执行时的环境非常干净,PATH 通常只有 /usr/bin:/bin,你 shell 里能跑的命令它可能找不到。比如 node、python3、docker 装在 /usr/local/bin,直接写命令名就会失败。

解决办法:命令用绝对路径,或者在 crontab 顶部显式设置环境变量:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SHELL=/bin/bash

0 3 * * * /usr/bin/python3 /home/app/backup.py >> /var/log/backup.log 2>&1

另外,cron 不读取 ~/.bashrc 和 ~/.profile,所以你在里面设的变量它一概不知。需要的话,在脚本开头手动 source 或直接写死。

看日志,别靠猜

如果任务确实触发了但命令失败,日志会告诉你原因。不同系统日志位置不同:

# Debian/Ubuntu
grep CRON /var/log/syslog

# CentOS/RHEL
grep CRON /var/log/cron

# 使用 journalctl
journalctl -u cron --since "10 min ago"

日志里会显示 cron 是否执行了该行,以及命令的退出状态。如果连执行记录都没有,说明时间表达式没匹配上,或者任务被 /etc/cron.allow、/etc/cron.deny 限制。

权限与特殊场景

普通用户只能管理自己的 crontab;要用 root 权限执行,得写进 root 的 crontab 或系统级目录。脚本本身要有可执行权限(如果直接执行脚本),或者用解释器调用。另外,服务器时区不对也会导致任务在“错误的时间”执行,用 timedatectl 确认时区。

最后,如果你在 Docker 容器里跑 cron,要确保容器前台进程不退出,并且 cron 服务已启动——很多镜像默认不带。

发表评论