脚本执行失败常因权限链中断,需逐级检查脚本、所在目录及父目录的r-x权限;脚本须chmod +x,目录须有x权限允许进入,且属主/selinux策略须匹配执行用户。

脚本执行失败常因权限问题被忽略,而 cron 对权限比交互式环境更敏感。关键不是“脚本能不能运行”,而是“cron 有没有权限以指定用户身份读取、进入、执行它”。
确认脚本和路径的完整权限链
从脚本本身向上逐级检查:文件 → 所在目录 → 父目录 → ……直到根目录。任意一级缺少 执行权限(x) 或 读权限(r),都会导致 cron 失败。
- 脚本必须有 可执行权限:chmod +x /path/to/script.sh(即使用 /bin/bash /path/to/script.sh 调用,也需 r 权限;若用 ./script.sh,则必须有 x)
- 脚本所在目录必须有 x 权限(允许进入),否则 cron 无法访问该文件;例如 /home/user/bin/ 需是 drwxr-xr-x,不能是 drw-r--r--
- 如果脚本中 cd 到其他路径(如 /data/backup),那 /data/ 和 /data/backup 也都必须对执行用户(如 www-data)有 r-x 权限
检查执行用户的实际权限上下文
cron 不继承你的登录会话权限,它严格按文件属主、属组和 umask 运行。常见陷阱:
- 脚本属主是 root,但 crontab 属于普通用户(如 ec2-user)→ cron 尝试以 ec2-user 身份读取 root:root 的脚本,会因无读权限失败
- 脚本放在 /tmp 下,但 /tmp 默认有 sticky bit(drwxrwxrwt),普通用户可写却不可读他人文件 → 若脚本由 root 创建、ec2-user 执行,可能被拒绝读取
- SELinux 启用时,即使传统权限全开,也可能因策略限制阻止访问(如 script_t 类型无法读取 user_home_t 下的文件);可用 sudo ausearch -m avc -ts recent 查看拒绝记录
验证方式要模拟真实执行场景
别只用 ls -l 看权限,要用 cron 实际使用的用户和最小环境去测试:
- 用 sudo -u username env -i PATH=/usr/bin:/bin /bin/sh -c 'ls -l /path/to/script.sh' 确认能否读取
- 再执行 sudo -u username env -i PATH=/usr/bin:/bin /bin/sh -c '/path/to/script.sh' 观察是否报 Permission denied 或 No such file or directory
- 若脚本内调用其他程序(如 python3、curl),同样检查这些二进制文件对执行用户是否可访问:sudo -u username which python3 && ls -l $(which python3)
修复建议优先级清晰
按风险与效果排序,避免过度授权:
- ✅ 首选:将脚本和依赖路径属主改为执行用户,如 sudo chown ec2-user:ec2-user /home/ec2-user/script.sh;目录设为 755,脚本设为 755 或 644(若用解释器显式调用)
- ⚠️ 次选:仅开放必要权限,如 sudo chmod 755 /home/ec2-user/bin/,而非 chmod 777
- ❌ 避免:把脚本放 /root 下并让普通用户执行;或关闭 SELinux / AppArmor 作为长期方案











