crontab不生效的原因与解决方法

在 Linux 服务器运维中,很多人会遇到一个非常常见、但也很坑的问题:

✅ crontab 明明加上了任务,语法也正确,crontab -l 能看到,cron 服务也在运行,但是任务就是没有执行。

更糟糕的是,/var/log/cron 里会出现类似下面的错误日志:

CROND[...] PAM ERROR (Permission denied)
CROND[...] FAILED to authorize user with PAM (Permission denied)

📌 一、问题现象

  • crontab 里配置了定时任务,比如:

    45 8 * * * /usr/bin/bash /path/to/your/script.sh 
  • cron 服务正常运行中:

    systemctl status crond 
  • 但在 /var/log/cron 中发现错误:

    PAM ERROR (Permission denied) FAILED to authorize user with PAM (Permission denied) 

📌 二、核心原因

这是 Linux 的 PAM(Pluggable Authentication Modules)访问控制 拒绝了 cron 的任务调用。

在很多系统(尤其是 CentOS、RHEL 系列)中,cron 的 PAM 配置文件 /etc/pam.d/crond 会包含这一行:

account    required   pam_access.so 

这行的意思是:
✅ crond 执行任务前会检查 PAM 的访问控制规则,
✅ 规则来源是 /etc/security/access.conf 文件。

/etc/security/access.conf 里通常会有一条“封死一切”的拒绝规则:

 : ALL : ALL 

这表示:默认拒绝所有用户来自所有来源的访问。

如果上面没有明确的“允许”规则,cron 就会因为 PAM 验证失败,任务完全不执行。

📌 三、排查步骤

1️⃣ 查看 PAM 的 cron 配置:

cat /etc/pam.d/crond 

看是否有:

account    required   pam_access.so 

如果有,就必须检查 /etc/security/access.conf

2️⃣ 查看 access.conf 内容:

cat /etc/security/access.conf 

通常会看到类似:

... # 其他允许规则 - : ALL : ALL 

3️⃣ 关键:cron 的「来源」字段

  • cron 任务在 PAM 验证时的来源字段是:

    cron

    crond 
  • 不同系统版本里可能不同,有些是 cron,有些是 crond。

  • 如果 access.conf 里没有为 root 账户写一个允许来自 cron / crond 的规则,就会被最后的 - : ALL : ALL 阻挡。

📌 四、解决方案

✅ 在 /etc/security/access.conf 中找到最后的拒绝行:

- : ALL : ALL 

✅ 在它上面加上允许 root 通过 cron 的规则:

+ : root : cron crond 

完整示例(末尾应该是这样的):

# 其他用户和组的允许规则 + : pmo01_group : 176.0.250.41 176.0.250.42 176.0.250.43 176.0.250.21 + : root : cron crond - : ALL : ALL

解释:

  • + : root : cron crond 表示允许用户 root 从「cron」或「crond」来源调用。

  • 这样 PAM 会在遇到拒绝规则之前,提前匹配到允许。

📌 五、修改后立即生效

  • 这个文件改完后 不需要重启 crond 服务,立刻生效。

  • cron 任务会在下一次调度时间点自动执行。

📌 六、验证方法

你可以写一个最简单的测试任务来确认:

crontab -e 

加上:

* * * * * echo hello >> /tmp/cron_test.log 

等待几分钟:

cat /tmp/cron_test.log 

如果文件里开始不断出现 hello,就说明 root 的 cron 权限问题已经解决。

📌 七、其他常见检查项

如果问题依然没解决,还可以检查:

✅ 1️⃣ /etc/cron.allow 和 /etc/cron.deny

  • 如果 /etc/cron.allow 存在,必须包含 root

  • /etc/cron.deny 不要包含 root

✅ 2️⃣ 确认 cron 服务在运行

systemctl status crond 

✅ 3️⃣ 确认系统时间 / 时区

date timedatectl 

cron 的调度是根据系统时间。

✅ 4️⃣ 脚本本身的可执行权限

chmod +x /path/to/script.sh

✅ 5️⃣ 脚本里的路径环境

  • cron 的环境变量很干净,建议在脚本里用绝对路径。

📌 八、总结

✅ 出现 PAM ERROR (Permission denied) 的真正原因:

/etc/security/access.conf 里没有允许 root 来自 cron 的访问。

✅ 解决办法:

在拒绝行上面加 + : root : cron crond

✅ 修改后立即生效,不需要重启。