Linux cron 任务未执行的排查清单

7次阅读

cron服务常未运行,需用systemctl status确认并启用;任务需日志验证是否加载;环境变量缺失是执行失败主因,应显式声明PATH或用bash -lc;脚本须有执行权限、绝对路径并记录完整日志。

Linux cron 任务未执行的排查清单

确认 cron 服务是否真在运行

很多“任务没执行”问题,根源其实是 crond 根本没跑起来——尤其在最小化安装或容器环境中,cron 服务默认可能未启用。

  • systemctl status crondebian/ubuntu)或 systemctl status crond(RHEL/centos)直接看状态,别只信 ps aux | grep cron
  • 若显示 inactive (dead),立刻启动:sudo systemctl start cron
  • 务必补上开机自启:sudo systemctl enable cron,否则重启后又失效
  • 注意:普通用户无权启停服务,service crond start 在非 root 下会静默失败

查日志:先看 cron 是否“认出”了你的任务

任务写进 crontab -e 不等于被加载。cron 只在重载配置或服务启动时读取一次,且日志里必须出现 CRONCMD 才算真正触发过。

  • 查执行痕迹:sudo journalctl -u cron | grep "CMD" | tail -10(systemd 系统)
  • 或翻传统日志:sudo grep CRON /var/log/syslog(Ubuntu)或 sudo tail -50 /var/log/cron(CentOS)
  • 如果日志里压根没你脚本的路径,说明:任务没生效(语法错/没保存)、用户权限被 /etc/cron.deny 拦住、或 crontab 文件被覆盖(如用 crontab /path/to/file 覆盖了原内容)

环境变量缺失:90% 的“手动能跑,cron 不行”都卡在这

cron 启动的是极简 shell(/bin/sh),PATH 只有 /usr/bin:/bin.bashrc.profile 全不加载——所以 python3nodemysqldump 找不到,sudoNo such file or Directory 都是常态。

  • 最稳妥解法:在 crontab 开头显式声明环境:
    SHELL=/bin/bash
    PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
  • 或改用 bash -lc 加载登录环境:0 2 * * * bash -lc '/path/to/script.sh > /tmp/log 2>&1'
  • 验证方法:在脚本第一行加 echo $PATH >> /tmp/env.log,对比手动执行时的输出
  • 注意:不要在脚本里盲目 . ~/.bash_profile——cron 用户家目录可能不是你预期的(如 root 家目录是 /root,但某些服务用户家目录为空)

脚本自身问题:日志和权限才是真相

即使 cron 日志显示 CMD(...),也只代表“调用了”,不代表“成功执行”。错误全藏在脚本内部或输出里。

  • 去掉重定向中的 >/dev/null 2>&1,让错误浮出水面;然后检查 /var/spool/mail/root(或对应用户邮箱)是否有 cron 发来的报错邮件
  • 给脚本加可执行权限:chmod +x /path/to/script.sh;同时确认脚本里所有调用的命令、路径(如 cd /data && ./app)都是绝对路径
  • 强制记录完整执行流:0 * * * * /path/to/script.sh >> /var/log/myscript.log 2>&1,日志里能看到每一步 stdout/stderr
  • 特别警惕:脚本里用了 ~$HOME,cron 下可能解析为空;用了 date +%Y%m%d 生成文件名,但目标目录不存在(需提前 mkdir -p

真正难缠的 case 往往是多个因素叠加:服务开着但用户被 cron.deny 拦住、PATH 不对导致命令找不到、脚本又因相对路径失败、最后还因没日志而无法定位——所以排查必须按顺序堵漏,不能只盯着某一个点反复试。

text=ZqhQzanResources