强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

故障排查

故障排查

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. 注意事项

  1. 先备份:排查前备份当前配置和日志
  2. 逐步排查:从最简单的可能原因开始
  3. 查看日志:错误日志是最重要的排查依据
  4. 测试环境:先在测试环境重现和修复问题
  5. 记录过程:记录排查步骤和解决方案

10. 扩展阅读

11. 总结

Apache 故障排查的核心方法:

  • 日志为王:错误日志和访问日志是最重要的排查工具
  • 配置验证:使用 configtest 确认配置正确
  • 分层排查:从网络层到应用层逐层排查
  • 工具辅助:curl、openssl、strace 等工具帮助定位问题
  • 经验积累:建立故障知识库,总结常见问题解决方案