如何解决Crontab无法以Root身份每5分钟执行Shell脚本的问题?
Crontab定时执行Shell脚本失败修复
一、必须修改的几个点
- 修正定时表达式:你写的
5/5 * * * *是错误的,要实现每5分钟执行一次,应该写成*/5 * * * *。5/5的逻辑是“每小时第5分钟开始,每5分钟跑一次”,不符合需求;*/5才是任意时间点每5分钟执行。 - 使用脚本绝对路径:crontab的默认工作目录是root的家目录
/root,./var/update-dns/updateDNS.sh这种相对路径会找不到文件,直接改成绝对路径/var/update-dns/updateDNS.sh。 - 给脚本添加执行权限:执行这条命令赋予脚本可执行权限:
chmod +x /var/update-dns/updateDNS.sh - 修复脚本逻辑与细节:
- 脚本开头加上
#!/bin/bash,明确指定bash解释器; - 脚本里
if [ $LOGFILE = "" ] ; then这个判断永远不会触发,因为LOGFILE已经被赋值,应改成判断日志文件是否存在:if [ ! -f "$LOGFILE" ] ; then; - 因为是root身份执行crontab,脚本里的
sudo可以直接删除,避免冗余权限调用; - crontab的PATH环境变量范围很窄,可能找不到
host、curl、ufw等命令,先查它们的绝对路径:
把脚本里的对应命令替换成绝对路径版本(比如which host curl ufw/usr/bin/host、/usr/bin/curl、/usr/sbin/ufw); - 建议给输出加上时间戳并追加到日志,方便排查问题,比如把
echo内容改成echo "$(date): 内容" >> $LOGFILE。
- 脚本开头加上
修正后的脚本参考:
#!/bin/bash /usr/bin/curl http://localhost/external_ip.php HOSTNAME=pi.marvinkleinmusic.de LOGFILE=/var/update-dns/log.txt Current_IP=$(/usr/bin/host $HOSTNAME | cut -f4 -d' ') if [ ! -f "$LOGFILE" ] ; then /usr/sbin/ufw allow from $Current_IP echo "$(date): 初始化IP规则,当前IP: $Current_IP" > $LOGFILE else Old_IP=$(cat $LOGFILE) if [ "$Current_IP" = "$Old_IP" ] ; then echo "$(date): IP地址未变化" >> $LOGFILE else /usr/sbin/ufw delete allow from $Old_IP /usr/sbin/ufw allow from $Current_IP echo $Current_IP > $LOGFILE echo "$(date): 防火墙规则已更新,旧IP: $Old_IP,新IP: $Current_IP" >> $LOGFILE fi fi
- 修正后的crontab条目:编辑root的crontab(
sudo crontab -e),添加这条规则:
末尾的*/5 * * * * /var/update-dns/updateDNS.sh >> /var/update-dns/cron.log 2>&1>> /var/update-dns/cron.log 2>&1是把脚本的输出和错误信息都重定向到日志文件,方便排查问题。
二、关于Crontab启用的问题
树莓派默认已经启用了cron服务,不确定的话可以查状态:
sudo systemctl status cron
如果显示active (running)就没问题;要是没启动,执行以下两条命令:
sudo systemctl start cron sudo systemctl enable cron
三、如何查看任务是否执行?
- 查看cron系统日志:cron的执行记录存在
/var/log/syslog里,用grep过滤查看:
如果任务执行了,会看到类似这样的记录:grep CRON /var/log/syslogJun 10 14:05:00 raspberrypi CRON[12345]: (root) CMD (/var/update-dns/updateDNS.sh >> /var/update-dns/cron.log 2>&1) - 查看脚本输出日志:直接查看你设置的
/var/update-dns/cron.log文件,里面会有脚本运行的输出和错误信息:cat /var/update-dns/cron.log - 检查日志文件修改时间:查看脚本生成的
/var/update-dns/log.txt的更新时间,判断是否每5分钟更新一次:ls -l /var/update-dns/log.txt
内容的提问来源于stack exchange,提问作者Marvin Klein
相关产品推荐
相关产品推荐

