应用故障排查

核心知识点

1. 应用故障类型

1.1 应用启动故障

┌─────────────────────────────────────────────────────┐
│              应用启动故障                           │
├─────────────────────────────────────────────────────┤
│                                                     │
│   ┌─────────────────────────────────────────┐       │
│   │           配置错误                     │       │
│   │  - 配置文件错误                         │       │
│   │  - 环境变量错误                         │       │
│   │  - 依赖项缺失                           │       │
│   └─────────────────────────────────────────┘       │
│                      │                              │
│   ┌─────────────────────────────────────────┐       │
│   │           权限问题                     │       │
│   │  - 文件权限不足                         │       │
│   │  - 端口权限不足                         │       │
│   │  - 用户权限不足                         │       │
│   └─────────────────────────────────────────┘       │
│                      │                              │
│   ┌─────────────────────────────────────────┐       │
│   │           资源不足                     │       │
│   │  - 内存不足                             │       │
│   │  - 磁盘空间不足                         │       │
│   │  - 端口被占用                           │       │
│   └─────────────────────────────────────────┘       │
│                      │                              │
│   ┌─────────────────────────────────────────┐       │
│   │           依赖问题                     │       │
│   │  - 库文件缺失                           │       │
│   │  - 服务依赖未启动                       │       │
│   │  - 版本不兼容                           │       │
│   └─────────────────────────────────────────┘       │
│                                                     │
└─────────────────────────────────────────────────────┘

1.2 应用运行时故障

故障类型 表现 常见原因
应用崩溃 进程退出 代码错误、异常未处理
响应慢 请求超时 性能瓶颈、资源不足
内存泄漏 内存持续增长 资源未释放、循环引用
CPU 爆满 CPU 使用率高 死循环、计算密集
死锁 应用无响应 资源竞争、锁等待

2. 应用监控工具

2.1 进程监控

# ps - 查看进程
ps aux
ps -ef
ps aux --sort=-%cpu
ps aux --sort=-%mem

# top - 实时监控
top
htop

# pstree - 进程树
pstree
pstree -p

# pgrep - 查找进程
pgrep -f <app-name>
pgrep -l <app-name>

2.2 资源监控

# 监控进程资源
pidstat -p <pid> 1
pidstat -d -p <pid> 1
pidstat -r -p <pid> 1

# 查看进程内存
pmap -x <pid>
cat /proc/<pid>/status
cat /proc/<pid>/maps

# 查看进程文件描述符
ls -la /proc/<pid>/fd
lsof -p <pid>

2.3 日志监控

# 查看应用日志
tail -f /var/log/app.log
tail -n 100 /var/log/app.log

# 查看系统日志
journalctl -u <service>
journalctl -f -u <service>

# 查看错误日志
grep -i error /var/log/app.log
grep -i error /var/log/syslog

3. 应用启动故障排查

3.1 配置错误排查

# 1. 检查配置文件
cat /etc/app/config.conf
cat /var/www/app/.env

# 2. 验证配置语法
app --config-check
nginx -t
apache2ctl configtest

# 3. 检查环境变量
env | grep APP_
printenv | grep APP_

# 4. 检查配置差异
diff /etc/app/config.conf /etc/app/config.conf.bak

# 5. 恢复配置
cp /etc/app/config.conf.bak /etc/app/config.conf

# 6. 重启应用
systemctl restart app

3.2 权限问题排查

# 1. 检查文件权限
ls -la /var/www/app
ls -la /etc/app

# 2. 检查用户权限
whoami
id

# 3. 修改文件权限
sudo chown -R www-data:www-data /var/www/app
sudo chmod -R 755 /var/www/app

# 4. 检查端口权限
sudo netstat -tlnp | grep <port>
sudo ss -tlnp | grep <port>

# 5. 检查 SELinux
getenforce
sestatus

# 6. 临时禁用 SELinux
sudo setenforce 0

3.3 资源不足排查

# 1. 检查内存使用
free -h
ps aux --sort=-%mem | head -20

# 2. 检查磁盘空间
df -h
du -sh /var/www/app

# 3. 检查端口占用
sudo netstat -tlnp | grep <port>
sudo ss -tlnp | grep <port>

# 4. 检查文件描述符
ulimit -n
cat /proc/<pid>/limits | grep "open files"

# 5. 增加资源限制
ulimit -n 65535
echo "* soft nofile 65535" >> /etc/security/limits.conf

# 6. 释放资源
sudo rm -rf /tmp/*
sudo journalctl --vacuum-time=7d

3.4 依赖问题排查

# 1. 检查库文件
ldd /usr/bin/app
ldd /usr/lib/libapp.so

# 2. 检查服务依赖
systemctl list-dependencies app
systemctl list-dependencies --reverse app

# 3. 检查包依赖
dpkg -I app.deb
rpm -qR app

# 4. 安装缺失依赖
sudo apt-get install -f
sudo yum install <dependency>

# 5. 检查版本兼容性
app --version
dpkg -l | grep app

# 6. 更新应用
sudo apt-get update
sudo apt-get upgrade app

4. 应用运行时故障排查

4.1 应用崩溃排查

# 1. 查看崩溃日志
tail -f /var/log/app.log
journalctl -u app -n 100

# 2. 查看系统日志
dmesg | grep -i app
cat /var/log/syslog | grep -i app

# 3. 查看核心转储
ls /var/crash/
ls /var/lib/systemd/coredump/

# 4. 分析核心转储
gdb /usr/bin/app /var/crash/core.<pid>
bt

# 5. 启用核心转储
echo "/tmp/core.%e.%p.%h.%t" > /proc/sys/kernel/core_pattern
ulimit -c unlimited

# 6. 调试应用
gdb /usr/bin/app
run
bt

4.2 响应慢排查

# 1. 监控进程资源
pidstat -p <pid> 1
top -p <pid>

# 2. 查看进程线程
ps -eLf | grep <pid>
top -H -p <pid>

# 3. 分析系统调用
strace -p <pid>
strace -c -p <pid>

# 4. 分析性能瓶颈
perf top -p <pid>
perf record -g -p <pid>
perf report

# 5. 查看网络连接
netstat -anp | grep <pid>
ss -anp | grep <pid>

# 6. 优化应用
# - 优化代码
# - 增加缓存
# - 调整配置

4.3 内存泄漏排查

# 1. 监控内存使用
watch -n 1 "cat /proc/<pid>/status | grep -i mem"
pidstat -r -p <pid> 1

# 2. 查看进程内存
pmap -x <pid>
cat /proc/<pid>/maps

# 3. 使用 valgrind 检测
valgrind --leak-check=full --show-leak-kinds=all ./myapp

# 4. 使用 address sanitizer
gcc -fsanitize=address -g myapp.c -o myapp
./myapp

# 5. 分析堆转储
jmap -dump:format=b,file=heap.bin <pid>
jhat heap.bin

# 6. 修复内存泄漏
# - 检查未释放的内存
# - 检查循环引用
# - 使用智能指针

4.4 CPU 爆满排查

# 1. 查看 CPU 使用
top -p <pid>
htop

# 2. 查看线程
ps -eLf | grep <pid>
top -H -p <pid>

# 3. 分析进程
strace -p <pid>
perf top -p <pid>

# 4. 查看调用栈
pstack <pid>
cat /proc/<pid>/stack

# 5. 分析代码
# - 查看热点函数
# - 查看死循环
# - 查看性能瓶颈

# 6. 优化代码
# - 优化算法
# - 减少计算
# - 使用缓存

4.5 死锁排查

# 1. 查看进程状态
ps aux | grep <pid>
cat /proc/<pid>/status

# 2. 查看线程状态
ps -eLf | grep <pid>
cat /proc/<pid>/task/*/status

# 3. 查看调用栈
cat /proc/<pid>/stack
cat /proc/<pid>/task/*/stack

# 4. 查看锁信息
# - 使用调试工具
# - 查看日志
# - 分析代码

# 5. 使用 gdb 调试
gdb -p <pid>
thread apply all bt

# 6. 解决死锁
# - 优化锁粒度
# - 使用读写锁
# - 避免嵌套锁

5. 应用日志分析

5.1 日志收集

# 1. 查看应用日志
tail -f /var/log/app.log
tail -n 100 /var/log/app.log

# 2. 查看系统日志
journalctl -u app
journalctl -f -u app

# 3. 查看错误日志
grep -i error /var/log/app.log
grep -i error /var/log/syslog

# 4. 查看访问日志
tail -f /var/log/nginx/access.log
tail -f /var/log/apache2/access.log

# 5. 导出日志
cp /var/log/app.log /tmp/app.log
tar -czf app-logs.tar.gz /var/log/app.log*

5.2 日志分析

# 1. 统计错误数量
grep -i error /var/log/app.log | wc -l

# 2. 查看最新错误
grep -i error /var/log/app.log | tail -20

# 3. 按时间过滤
grep "2024-01-01 10:" /var/log/app.log

# 4. 按关键词过滤
grep "keyword" /var/log/app.log

# 5. 统计访问量
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr

# 6. 分析响应时间
awk '{print $NF}' /var/log/nginx/access.log | sort -n | tail -10

5.3 日志可视化

# 1. 使用 ELK Stack
# - 安装 Elasticsearch
# - 安装 Logstash
# - 安装 Kibana

# 2. 配置 Logstash
cat > /etc/logstash/conf.d/app.conf << 'EOF'
input {
  file {
    path => "/var/log/app.log"
    start_position => "beginning"
  }
}
output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "app-logs"
  }
}
EOF

# 3. 启动服务
systemctl start logstash
systemctl start elasticsearch
systemctl start kibana

# 4. 访问 Kibana
# http://localhost:5601

实用案例分析

案例 1:Web 应用无法启动

场景描述

Nginx Web 应用无法启动。

排查步骤

# 1. 检查服务状态
systemctl status nginx

# 2. 查看服务日志
journalctl -u nginx -n 100
tail -f /var/log/nginx/error.log

# 3. 验证配置文件
nginx -t

# 4. 检查端口占用
sudo netstat -tlnp | grep :80
sudo ss -tlnp | grep :80

# 5. 检查文件权限
ls -la /var/www/html
ls -la /etc/nginx

# 6. 修复配置
sudo nano /etc/nginx/nginx.conf

# 7. 重启服务
sudo systemctl restart nginx

# 8. 验证效果
curl http://localhost/

案例 2:数据库应用响应慢

场景描述

MySQL 数据库查询响应慢。

排查步骤

# 1. 检查数据库状态
systemctl status mysql
mysqladmin -u root -p status

# 2. 查看慢查询
mysql -u root -p -e "SHOW VARIABLES LIKE 'slow_query_log';"
tail -f /var/log/mysql/slow.log

# 3. 分析查询计划
mysql -u root -p -e "EXPLAIN SELECT * FROM users WHERE id = 1;"

# 4. 添加索引
mysql -u root -p -e "CREATE INDEX idx_id ON users(id);"

# 5. 优化查询
mysql -u root -p -e "SELECT id, name FROM users WHERE id = 1;"

# 6. 调整缓冲池
mysql -u root -p -e "SET GLOBAL innodb_buffer_pool_size = 2G;"

# 7. 验证效果
mysql -u root -p -e "SHOW STATUS LIKE 'Slow_queries';"

案例 3:Java 应用内存泄漏

场景描述

Java 应用内存持续增长。

排查步骤

# 1. 监控内存使用
jstat -gc <pid>
jmap -heap <pid>

# 2. 分析堆转储
jmap -dump:format=b,file=heap.bin <pid>
jhat heap.bin

# 3. 使用 MAT 分析
# - 下载 MAT
# - 打开 heap.bin
# - 分析内存泄漏

# 4. 优化 JVM 参数
java -Xms512m -Xmx1024m -XX:+UseG1GC -jar myapp.jar

# 5. 检查代码
# - 检查未释放的对象
# - 检查循环引用
# - 检查缓存使用

# 6. 验证效果
jstat -gc <pid>

最佳实践

  1. 完善日志记录:记录关键操作和错误信息。

  2. 配置监控告警:及时发现应用问题。

  3. 定期备份配置:便于快速恢复。

  4. 使用版本控制:管理应用配置和代码。

  5. 建立文档:记录问题和解决方案。

  6. 定期测试:验证应用功能。

  7. 性能优化:持续优化应用性能。

  8. 安全加固:保护应用安全。

总结

本教程详细介绍了 Linux 系统应用故障的排查方法和实践。通过实际案例,我们学习了如何排查应用启动故障和运行时故障,以及如何使用监控工具和日志分析工具。掌握这些知识后,可以快速定位和解决应用级问题。

« 上一篇 网络故障排查 下一篇 » 性能问题排查