Linux系统CPU高负载排查
一、核心排查工具
1. PS命令
基础进程查询:
# 按CPU使用率降序排序(显示前10)
ps aux --sort=-%cpu | head -n 11
# 按内存使用率排序
ps aux --sort=-%mem | head -n 5
# 按运行时间排序
ps aux --sort=-time | head -n 5
线程级分析:
# 查看指定进程的所有线程
ps -eLf | grep [PID]
# 按CPU时间排序线程
ps -mp [PID] -o THREAD,tid,time | sort -rn
# 显示线程状态
ps -T -p [PID]
进程树分析:
# 显示进程树关系
pstree -p [PID]
# 显示完整进程信息
ps -fp [PID]
2. TOP命令高级用法
# 实时监控(按CPU排序)
top -o %CPU
# 指定更新间隔
top -d 2 -n 5
# 线程级监控
top -H -p [PID]
二、组合排查策略
1. 组合使用
# 组合TOP和PS
top -b -n 1 | grep "Cpu(s)" && ps aux --sort=-%cpu | head -n 11
# 综合资源分析
ps aux --sort=-%cpu,-%mem | head -n 11
2. 历史记录关联分析
# 结合历史命令排查
history | grep [PID]
# 检查最近登录
last | grep "pts"
三、场景示例
场景1:Java应用高CPU排查
# 1. 定位Java进程
ps aux | grep java | sort -k3 -nr | head -n 5
# 2. 线程分析
ps -mp [PID] -o THREAD,tid,time | sort -rn
# 3. 线程转储
jstack [PID] | grep -A 20 [TID]
场景2:系统进程异常
# 1. 检查系统进程
ps aux | grep -E 'systemd|kernel' | sort -k3 -nr | head -n 5
# 2. 内核线程检查
cat /proc/[PID]/status | grep Threads
# 3. 进程权限检查
ls -l /proc/[PID]/exe
四、进阶分析技巧
1. 实时监控脚本
# 动态监控脚本
watch -n 1 "ps aux --sort=-%cpu | head -n 11"
# 资源趋势记录
while true; do
date +"%H:%M:%S";
ps aux --sort=-%cpu | head -n 5;
sleep 5;
done > cpu_monitor.log
2. 日志关联分析
# 结合系统日志
grep "CPU load" /var/log/messages | tail -n 20
# 应用日志分析
grep "ERROR" /var/log/app.log | awk '{print $2}'
3. 性能基线建立
# 建立性能基线
ps aux --sort=-%cpu > baseline_$(date +%Y%m%d).txt
# 对比分析
diff baseline_20250821.txt current_scan.txt
3. 完整脚本
# cpu_monitor.sh
#!/bin/sh
# 智能CPU监控脚本(带后台控制)
THRESHOLD=300
CHANGE_THRESHOLD=10
LOG_DIR="$(dirname "$0")/cpu_logs"
MAX_LOG_DAYS=7
CHECK_INTERVAL=60
PID_FILE="/tmp/cpu_monitor.pid"
case "$1" in
start)
if [ -f "$PID_FILE" ]; then
if kill -0 $(cat "$PID_FILE") 2>/dev/null; then
echo "监控已在运行 (PID: $(cat "$PID_FILE"))"
exit 1
else
rm -f "$PID_FILE"
fi
fi
nohup "$0" daemon >/dev/null 2>&1 &
echo $! > "$PID_FILE"
echo "CPU监控已启动 (PID: $!)"
;;
stop)
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if kill -0 $PID 2>/dev/null; then
kill $PID
rm -f "$PID_FILE"
echo "CPU监控已停止"
else
rm -f "$PID_FILE"
echo "监控进程不存在,已清理PID文件"
fi
else
echo "监控未运行"
fi
;;
status)
if [ -f "$PID_FILE" ]; then
PID=$(cat "$PID_FILE")
if kill -0 $PID 2>/dev/null; then
echo "CPU监控正在运行 (PID: $PID)"
else
rm -f "$PID_FILE"
echo "监控进程已停止"
fi
else
echo "监控未运行"
fi
;;
daemon)
clean_old_logs() {
mkdir -p "$LOG_DIR"
find "$LOG_DIR" -name "cpu_alert_*.log" -mtime +$MAX_LOG_DAYS -exec rm {} \;
}
last_sum=0
last_alert_time=0
monitor() {
clean_old_logs
current_sum=$(ps -eo %cpu --sort=-%cpu | head -n 10 | awk '{s+=$1} END {print int(s)}')
current_time=$(date +%s)
sum_diff=$((current_sum - last_sum))
if [ "$current_sum" -gt "$THRESHOLD" ]; then
if [ "$last_sum" -le "$THRESHOLD" ] || \
[ $((current_time - last_alert_time)) -ge 3600 ] || \
[ ${sum_diff#-} -ge "$CHANGE_THRESHOLD" ]; then
log_alert "$current_sum" "$sum_diff"
last_alert_time=$current_time
fi
fi
last_sum=$current_sum
}
log_alert() {
log_file="$LOG_DIR/cpu_alert_$(date +%Y%m%d).log"
echo "[$(date "+%Y-%m-%d %H:%M:%S")] CPU负载警报: $1% (变化: $2%)" >> "$log_file"
ps -eo pid,user,ppid,%cpu,cmd --sort=-%cpu | head -n 11 >> "$log_file"
echo "----------------------------------------" >> "$log_file"
}
trap "rm -f '$PID_FILE'; exit 0" INT TERM
while :; do
monitor
sleep "$CHECK_INTERVAL"
done
;;
*)
echo "用法: $0 {start|stop|status}"
exit 1
;;
esac
701

被折叠的 条评论
为什么被折叠?



