CentOS 7下Cron执行Let's Encrypt证书续期脚本异常排查
问题诊断与修复方案
看你遇到的这个问题,手动跑脚本一切正常,但Cron自动执行时要么防火墙没关导致续期失败,要么续期成了但httpd和firehol没按预期重启,核心问题其实出在脚本格式错误和缺少必要的解释器声明上,下面给你拆解原因和修复步骤:
1. 脚本的致命格式问题:命令未正确分隔
你把所有命令堆在了同一行,而且没加分隔符,这会让系统把后面的命令全当成前一个命令的参数来执行。比如实际执行时,第一行变成了:
service firehol stop certbot renew --renew-by-default service httpd restart service firehol start
这完全不是你想要的顺序执行4个操作,而是让service firehol stop接收一堆无效参数,自然不会正确停止防火墙,后续的certbot、httpd操作根本没机会触发。
2. 缺少Shebang声明导致Cron执行环境异常
脚本开头没指定解释器(比如#!/bin/bash),Cron默认会用/bin/sh来跑脚本。虽然很多环境里/bin/sh是bash的软链接,但它的行为和交互bash有差异,还可能导致环境变量不全,影响命令的正常执行。
具体修复步骤
步骤1:重写脚本,修正格式并添加Shebang
把脚本改成下面的样子,每个命令单独一行(或者用分号分隔),开头加上shebang声明:
#!/bin/bash # 停止firehol防火墙 service firehol stop # 执行Let's Encrypt证书续期 certbot renew --renew-by-default # 重启httpd服务 service httpd restart # 重新启动firehol防火墙 service firehol start
这样每个命令都会被独立执行,严格按照你预期的顺序运行。
步骤2:给脚本添加可执行权限
确保Cron能正常运行脚本,执行下面的命令添加权限:
chmod +x /backup/checklecert.sh
步骤3:优化Cron配置(可选但推荐)
为了方便后续排查问题,可以在Cron里指定完整的解释器路径,同时把错误输出也重定向到日志:
10 20 * * 1 /bin/bash /backup/checklecert.sh > /backup/log/checklecert.txt 2>&1
这里2>&1是把错误日志和普通日志写到同一个文件里,万一再出问题,直接看日志就能找到原因。
额外优化建议
- 可以给脚本加详细日志输出,每个步骤执行后记录时间和状态,方便定位问题:
#!/bin/bash LOG_FILE="/backup/log/checklecert_detail.log" echo "[$(date +'%Y-%m-%d %H:%M:%S')] 开始停止firehol防火墙..." >> $LOG_FILE service firehol stop >> $LOG_FILE 2>&1 echo "[$(date +'%Y-%m-%d %H:%M:%S')] 开始执行证书续期..." >> $LOG_FILE certbot renew --renew-by-default >> $LOG_FILE 2>&1 echo "[$(date +'%Y-%m-%d %H:%M:%S')] 开始重启httpd服务..." >> $LOG_FILE service httpd restart >> $LOG_FILE 2>&1 echo "[$(date +'%Y-%m-%d %H:%M:%S')] 开始重新启动firehol防火墙..." >> $LOG_FILE service firehol start >> $LOG_FILE 2>&1 echo "[$(date +'%Y-%m-%d %H:%M:%S')] 所有步骤执行完成" >> $LOG_FILE - 测试脚本时可以用
bash -x /backup/checklecert.sh,能看到每一步的执行细节,确认没问题再放到Cron里。
内容的提问来源于stack exchange,提问作者Sean W.
相关产品推荐
相关产品推荐

