故障排查
故障排查
Apache 运行过程中可能遇到各种问题。本章整理常见错误、调试方法和故障排查流程。
1. 启动失败排查
1.1 端口被占用
# 症状
# (98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80
# 排查
sudo ss -tlnp | grep ':80'
sudo lsof -i :80
sudo fuser 80/tcp
# 解决
sudo kill $(sudo fuser 80/tcp 2>/dev/null | tr -d ' ')
sudo systemctl start apache2
1.2 配置语法错误
# 症状
# AH00526: Syntax error on line 42 of /etc/apache2/sites-enabled/example.conf
# Invalid command 'RewrteEngine', perhaps misspelled or defined by a module not included
# 排查
apachectl configtest
# Syntax error 会指出具体文件和行号
# 解决
# 修复语法错误后重新测试
sudo apachectl configtest
# Syntax OK
sudo systemctl restart apache2
1.3 模块加载失败
# 症状
# Cannot load modules/mod_ssl.so into server: libssl.so.1.1: cannot open shared object file
# 排查
apachectl -M 2>&1 | grep -i error
ldd /usr/lib/apache2/modules/mod_ssl.so
# 解决
# 安装缺失的依赖库
sudo apt install libssl-dev
# 或重新编译模块
1.4 权限问题
# 症状
# (13)Permission denied: AH00072: make_sock: could not bind to address 0.0.0.0:80
# (13)Permission denied: could not open error log file
# 排查
ls -la /var/log/apache2/
ls -la /var/www/html/
id www-data
# 解决
sudo chown -R root:root /var/log/apache2
sudo chmod 755 /var/log/apache2
sudo chown -R www-data:www-data /var/www/html
# SELinux 问题 (CentOS/RHEL)
sudo getenforce
sudo setenforce 0 # 临时关闭
sudo setsebool -P httpd_can_network_connect 1
1.5 PID 文件问题
# 症状
# AH00543: httpd: bad user name apache
# 排查
cat /var/run/apache2/apache2.pid
ls -la /var/run/apache2/
# 解决
sudo rm -f /var/run/apache2/apache2.pid
sudo systemctl start apache2
2. HTTP 错误排查
2.1 403 Forbidden
# 症状
# You don't have permission to access / on this server
# 排查步骤
# 1. 检查文件权限
ls -la /var/www/html/
# 需要 755 目录和 644 文件
# 2. 检查目录配置
apachectl -S
grep -r "Require" /etc/apache2/
# 3. 检查 .htaccess
cat /var/www/html/.htaccess
# 4. 检查 SELinux
ls -laZ /var/www/html/
sudo restorecon -Rv /var/www/html/
# 解决
# 修复权限
sudo chmod 755 /var/www/html
sudo chmod 644 /var/www/html/index.html
# 修复目录配置
<Directory "/var/www/html">
Require all granted
</Directory>
# 修复 SELinux
sudo setsebool -P httpd_enable_homedirs 1
sudo chcon -R -t httpd_sys_content_t /var/www/html/
2.2 404 Not Found
# 症状
# The requested URL was not found on this server
# 排查步骤
# 1. 检查文件是否存在
ls -la /var/www/html/index.html
# 2. 检查 DocumentRoot
apachectl -S | grep DocumentRoot
# 3. 检查 URL 重写规则
grep -r "RewriteRule" /etc/apache2/
# 4. 检查 Alias
grep -r "Alias" /etc/apache2/
# 解决
# 确认文件路径正确
# 检查重写规则
# 确认虚拟主机配置
2.3 500 Internal Server Error
# 症状
# The server encountered an internal error
# 排查步骤
# 1. 查看错误日志
tail -50 /var/log/apache2/error.log
# 2. 常见原因
# - .htaccess 语法错误
# - PHP 脚本错误
# - 权限问题
# - 内存不足
# 3. 检查 .htaccess 语法
cat /var/www/html/.htaccess
# 4. 检查 PHP 错误日志
tail -50 /var/log/php/error.log
# 解决
# 修复 .htaccess
# 增加 PHP 内存限制
# 修复脚本错误
2.4 502 Bad Gateway
# 症状
# 502 Bad Gateway (反向代理/PHP-FPM 场景)
# 排查步骤
# 1. 检查后端服务
curl http://localhost:8080/ # 直接访问后端
# 2. 检查 PHP-FPM 状态
sudo systemctl status php8.2-fpm
ls -la /run/php/php8.2-fpm.sock
# 3. 检查代理配置
grep -r "ProxyPass" /etc/apache2/
# 4. 查看错误日志
tail -50 /var/log/apache2/error.log
# 解决
# 确保后端服务运行
sudo systemctl start php8.2-fpm
# 检查 socket 权限
sudo chmod 660 /run/php/php8.2-fpm.sock
sudo chown www-data:www-data /run/php/php8.2-fpm.sock
# 增加超时时间
ProxyTimeout 300
2.5 503 Service Unavailable
# 症状
# 503 Service Unavailable
# 排查步骤
# 1. 检查进程数
ps aux | grep httpd | wc -l
# 2. 检查服务器状态
curl http://localhost/server-status?auto
# 3. 检查系统资源
free -m
df -h
top
# 解决
# 增加 MaxRequestWorkers
# 增加服务器资源
# 优化应用性能
3. SSL/TLS 问题排查
3.1 证书错误
# 症状
# SSL: error:0906D06C:PEM routines:PEM_read_bio:no start line
# 排查
openssl x509 -in /etc/ssl/certs/server.crt -text -noout
openssl rsa -in /etc/ssl/private/server.key -check
# 检查证书匹配
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
# 两个 MD5 应该相同
# 检查证书链
openssl verify -CAfile chain.pem server.crt
3.2 协议版本错误
# 症状
# SSL: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
# 排查
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
# 检查协议配置
grep "SSLProtocol" /etc/apache2/sites-enabled/*.conf
# 解决
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
3.3 混合内容
# 症状
# 页面显示但浏览器提示"不安全"
# 排查
# 浏览器 F12 → Console → 查看混合内容警告
curl -s https://example.com | grep -i "http://"
# 解决
Header always set Content-Security-Policy "upgrade-insecure-requests"
4. 性能问题排查
4.1 响应缓慢
# 排查步骤
# 1. 检查服务器负载
uptime
top
vmstat 1 5
# 2. 检查 Apache 状态
curl http://localhost/server-status?auto
# 3. 检查慢请求
awk '$NF > 5000000 {print}' /var/log/apache2/access.log | tail -20
# 4. 检查磁盘 I/O
iostat -x 1 5
# 5. 检查网络
ss -s
ping -c 5 localhost
# 解决
# 调整 MPM 参数
# 启用缓存
# 优化 PHP-FPM
# 使用 CDN
4.2 内存问题
# 排查
ps aux --sort=-%mem | head -10
pmap $(pgrep -o apache2) | tail -1
# 计算每个进程内存
ps aux | grep httpd | awk '{sum+=$6; count++} END {print "平均: " sum/count/1024 " MB"}'
# 解决
# 减少 MaxRequestWorkers
# 优化模块加载
# 检查内存泄漏
MaxConnectionsPerChild 10000
4.3 连接问题
# 排查
ss -s
ss -tlnp | grep ':80'
netstat -an | grep ':80' | awk '{print $6}' | sort | uniq -c
# 检查 TIME_WAIT
netstat -an | grep TIME_WAIT | wc -l
# 解决 (系统参数调整)
# /etc/sysctl.conf
# net.ipv4.tcp_tw_reuse = 1
# net.ipv4.tcp_fin_timeout = 30
# net.core.somaxconn = 65535
sudo sysctl -p
5. 调试方法
5.1 启用详细日志
# 调试级别日志
LogLevel debug
LogLevel trace1
LogLevel trace4
# 按模块设置日志级别
LogLevel alert rewrite:trace3
LogLevel debug ssl:trace1
LogLevel info proxy:trace2
# 按虚拟主机设置
<VirtualHost *:80>
ServerName debug.example.com
LogLevel debug
</VirtualHost>
5.2 重写日志
# 启用重写日志
LogLevel alert rewrite:trace3
# 日志输出示例:
# [rewrite:trace3] applying pattern '^(.*)$' to uri 'test'
# [rewrite:trace2] rewrite 'test' -> 'index.php?url=test'
# [rewrite:trace3] split uri=index.php?url=test -> uri=index.php, args=url=test
5.3 SSL 调试
# 测试 SSL 连接
openssl s_client -connect example.com:443 -servername example.com
# 查看证书信息
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -text -noout
# 测试特定协议
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
# 检查密码套件
nmap --script ssl-enum-ciphers -p 443 example.com
5.4 网络调试
# 使用 curl 调试
curl -v http://localhost/
curl -I http://localhost/
curl -L -v http://localhost/ # 跟踪重定向
# 使用 tcpdump
sudo tcpdump -i any -A port 80
# 使用 ngrep
sudo ngrep -d any -q -W byline "HTTP" port 80
# 测试 DNS
nslookup example.com
dig example.com
5.5 strace 调试
# 跟踪 Apache 进程
sudo strace -p $(pgrep -o apache2) -e trace=open,read,write
# 跟踪系统调用
sudo strace -f -p $(pgrep -o apache2) -o /tmp/strace.log
# 分析输出
grep -i "error\|permission\|denied" /tmp/strace.log
6. 日志分析方法
6.1 错误日志模式
# 常见错误日志格式
# [日期] [模块:级别] [pid:tid] [client IP] 消息
# 分析错误类型
awk -F']' '{print $2}' /var/log/apache2/error.log | sort | uniq -c | sort -rn
# 按时间分析
grep "$(date +%Y-%m-%d)" /var/log/apache2/error.log | wc -l
# 按 IP 分析错误
grep "\[client" /var/log/apache2/error.log | \
awk -F'client ' '{print $2}' | awk -F']' '{print $1}' | \
sort | uniq -c | sort -rn | head -20
6.2 访问日志分析
# 分析 5xx 错误
awk '$9 >= 500' /var/log/apache2/access.log | \
awk '{print $7, $9}' | sort | uniq -c | sort -rn
# 分析慢请求
awk '$NF > 5000000 {print $7, $NF/1000000 "s"}' /var/log/apache2/access.log
# 分析请求量
awk '{print $4}' /var/log/apache2/access.log | cut -d: -f1-3 | uniq -c
# 分析带宽
awk '{sum+=$10} END {print sum/1024/1024 " MB"}' /var/log/apache2/access.log
7. 常见故障排查流程图
7.1 Apache 无法启动
启动失败
├── 检查配置语法
│ └── apachectl configtest
│ ├── 语法错误 → 修复配置
│ └── 语法正确
│ ├── 检查端口占用
│ │ ├── 被占用 → 释放端口
│ │ └── 未被占用
│ │ ├── 检查权限
│ │ ├── 检查 PID 文件
│ │ └── 检查模块加载
│ └── 查看详细日志
└── journalctl -u apache2
7.2 502 Bad Gateway
502 Bad Gateway
├── 检查后端服务状态
│ ├── 未运行 → 启动后端
│ └── 运行中
│ ├── 检查 socket/端口
│ ├── 检查代理配置
│ ├── 检查防火墙
│ └── 检查超时设置
└── 查看错误日志
8. 业务场景
8.1 上线后问题排查
# 快速检查清单
#!/bin/bash
echo "=== Apache 快速诊断 ==="
# 服务状态
systemctl is-active apache2
# 配置测试
apachectl configtest
# 端口监听
ss -tlnp | grep -E ':80|:443'
# 网站响应
curl -s -o /dev/null -w "%{http_code}" http://localhost/
# 进程数
ps aux | grep apache2 | wc -l
# 磁盘空间
df -h | grep -E '/$|/var'
# 内存使用
free -m
# 最近错误
tail -5 /var/log/apache2/error.log
8.2 紧急回滚
#!/bin/bash
# rollback-apache.sh
# 恢复配置
sudo cp /etc/apache2/backup/apache2.conf.bak /etc/apache2/apache2.conf
sudo cp /etc/apache2/backup/sites-available/* /etc/apache2/sites-available/
# 测试配置
sudo apachectl configtest
# 重启服务
sudo systemctl restart apache2
# 验证
curl -s -o /dev/null -w "%{http_code}" http://localhost/
9. 注意事项
- 先备份:排查前备份当前配置和日志
- 逐步排查:从最简单的可能原因开始
- 查看日志:错误日志是最重要的排查依据
- 测试环境:先在测试环境重现和修复问题
- 记录过程:记录排查步骤和解决方案
10. 扩展阅读
11. 总结
Apache 故障排查的核心方法:
- 日志为王:错误日志和访问日志是最重要的排查工具
- 配置验证:使用 configtest 确认配置正确
- 分层排查:从网络层到应用层逐层排查
- 工具辅助:curl、openssl、strace 等工具帮助定位问题
- 经验积累:建立故障知识库,总结常见问题解决方案