Apache作为目前使用广泛的开源Web服务器,承载着大量网站的对外服务。服务进程一旦异常退出或假死,页面将无法访问,如果没有及时发现,损失会随时间放大。与其等用户反馈,不如用脚本主动巡检。本文介绍几种判断Apache运行状态的方法,并给出一个可直接落地的健康检查脚本,配合定时任务实现自动检测和自动恢复。

一、判断Apache是否存活的几种方式
判断Apache是否正常,不能只看一个维度。进程存在不代表能正常响应请求,端口在监听也不代表页面能正确返回。实际运维中通常把下面几种方法组合起来使用。
第一种是检查进程。Apache的主进程通常叫httpd(CentOS/RHEL系)或apache2(Debian/Ubuntu系),可以用ps命令配合grep统计进程数量:
ps aux | grep -v grep | grep httpd | wc -l
如果结果大于0说明进程存在。但进程存在只能说明“活着”,不能说明“健康”,因为Apache可能出现worker进程全部卡死、主进程还在的情况,这种假死状态用进程检查是发现不了的。
第二种是检查端口监听。默认配置下Apache监听80和443端口,可以用ss或netstat查看:
ss -tlnp | grep -w :80
第三种是请求真实页面。这是最可靠的方式,用curl访问本机的一个页面,检查HTTP返回码是否为200:
curl -s -o /dev/null -w "%{http_code}" --max-time 5 http://127.0.0.1/
只有返回码为200,才能证明从网络层到应用层整条链路都是通的。建议健康检查脚本以这种方式为主,进程和端口检查为辅。
二、完整的健康检查脚本实现
下面是一个综合了状态检测、自动重启和日志记录的完整脚本,适用于使用systemd管理系统(CentOS 7+、Ubuntu 16.04+等)。脚本逻辑是:先用systemctl is-active判断服务状态,再用curl探测页面,两者任一失败即认为服务异常,尝试重启并记录日志。
#!/bin/bash
# Apache服务名称,CentOS为httpd,Ubuntu为apache2
SERVICE="httpd"
# 健康检查地址
URL="http://127.0.0.1/"
# 日志文件
LOG_FILE="/var/log/apache_health_check.log"
check_time=$(date "+%Y-%m-%d %H:%M:%S")
# 第一步:检查服务状态
service_status=$(systemctl is-active $SERVICE)
# 第二步:检查页面返回码
http_code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 $URL)
if [ "$service_status" = "active" ] && [ "$http_code" = "200" ]; then
# 一切正常,只在调试时输出,不写日志避免刷屏
exit 0
fi
# 服务异常,记录并尝试重启
echo "[$check_time] 检测到异常: status=$service_status, http_code=$http_code" >> $LOG_FILE
systemctl restart $SERVICE
sleep 3
# 重启后再次验证
new_code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 $URL)
if [ "$new_code" = "200" ]; then
echo "[$check_time] 重启成功,服务已恢复" >> $LOG_FILE
else
echo "[$check_time] 重启后仍异常,http_code=$new_code,需要人工介入" >> $LOG_FILE
# 可在此处接入邮件或钉钉告警
fi
几点细节需要注意。curl必须加--max-time参数,否则当Apache假死不响应时,curl会一直挂起,脚本卡死导致后续的定时任务全部堆积。grep -v grep的作用是排除grep自身进程,避免误判。日志文件建议放在/var/log目录下并定期清理,防止无限增长。
另外要注意探测页面的选择。如果首页是动态页面(比如PHP程序),它依赖数据库,数据库挂了也会导致返回非200,此时脚本会重启Apache,但问题根源并不在Apache。更稳妥的做法是专门放一个纯静态的HTML页面用于健康检查,比如health.html,这样探测结果才能真实反映Apache本身的状态。
三、配合crontab定时执行与告警通知
脚本写好后需要让它周期性运行。把脚本保存为/opt/scripts/apache_check.sh并赋予执行权限,然后编辑crontab:
chmod +x /opt/scripts/apache_check.sh crontab -e # 每1分钟执行一次 * * * * * /opt/scripts/apache_check.sh > /dev/null 2>&1
每分钟一次的频率基本可以满足绝大多数场景。如果网站规模大、对可用性要求极高,可以把间隔缩短到30秒,但要注意脚本执行时间必须远小于间隔,避免上一次还没跑完下一次又启动。使用systemd托管的系统也可以用systemd timer代替crontab,精度更高且支持秒级触发。
仅有自动重启还不够。如果重启失败,说明问题可能出在配置错误、端口被占用或磁盘满了,此时必须通知到人。简单的告警可以用系统自带的mail命令:
echo "Apache重启后仍异常,请尽快处理 $(hostname)" | mail -s "Apache告警" ops@ipipp.com
如果团队使用钉钉或企业微信,创建一个机器人webhook,用curl POST一段JSON即可推送告警消息,实现方式简单且消息到达率高。告警内容里建议带上主机名、时间和当时的HTTP返回码,方便值班人员快速定位。
四、常见误区与改进方向
实践中一个常见误区是只依赖进程存活判断。前面提到过,Apache假死时主进程依然存在,端口也可能还在监听,但请求无法被处理。所以健康检查的核心指标必须是真实请求的返回结果,进程和端口只能作为辅助参考。
另一个误区是探测一次失败就重启。网络抖动、瞬间高负载都可能造成一次探测超时,直接重启反而造成正常的服务中断。更合理的策略是连续失败N次(比如3次)才判定为故障,脚本里可以用一个状态文件记录连续失败次数,达到阈值再触发重启。
在可靠性要求更高的场景下,还可以做更深入的探测,例如检查mod_status输出的空闲worker数量,当空闲worker长期为0时说明请求积压严重,虽然服务还没完全挂掉但已经接近过载,提前介入比事后重启更有价值。把这套健康检查脚本公司化、标准化后,配合Prometheus等监控系统对接,就能形成从探测、告警到自愈的完整运维闭环。
Apache健康检查Apache服务监控Linux运维脚本修改时间:2026-09-09 02:14:37