当前位置:首页>Linux>Linux Web 服务故障分析

Linux Web 服务故障分析

  • 2026-10-11 08:02:51
Linux Web 服务故障分析

一、系统连接状态篇

1. 查看 TCP 连接状态

传统 netstat 方式:

netstat-nat|awk'{print $6}'|sort|uniq-c|sort-rn

# 更简洁的统计
netstat-n|awk'/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
现代推荐:ss 命令(更快,信息更丰富)
# 查看各状态连接数
ss -ant|awk'NR>1 {print $1}'|sort|uniq-c|sort-rn

# 查看所有连接状态详情
ss -s

# 按状态统计
ss -ant|awk'NR>1 {state[$1]++} END {for(s in state) print state[s], s}'

# 查看连接状态及对应的进程
ss -antp
查看连接状态说明:
状态
含义
ESTABLISHED
已建立连接
SYN_SENT
正在发起连接
SYN_RECV
收到SYN,等待确认
FIN_WAIT1
等待远程TCP连接中断请求
FIN_WAIT2
等待远程TCP连接中断请求确认
TIME_WAIT
等待足够的时间以确保远程TCP接收到连接中断请求确认
CLOSED
没有任何连接状态
CLOSE_WAIT
等待从本地用户发来的连接中断请求
LAST_ACK
等待原来的发向远程TCP的连接中断请求确认
LISTEN
监听状态
CLOSING
等待远程TCP对连接中断的确认

2. 查找请求最多的 IP(常用于查找攻击来源)

# 传统方式
netstat-anlp|grep80|grep tcp |awk'{print $5}'|awk -F: '{print $1}'|sort|uniq-c|sort-nr|head-n20

# 更高效的 ss 方式
ss -ant|grep':80'|awk'{split($5,a,":"); print a[1]}'|sort|uniq-c|sort-nr|head-n20

# 使用 awk 直接处理(无需多次管道)
ss -ant|awk'/:80/ && NR>1 {split($5,ip,":"); ++A[ip[1]]} END {for(i in A) print A[i], i}'|sort-rn|head-n20

3. 用 tcpdump 嗅探 80 端口,找出访问最多的 IP

tcpdump -i eth0 -tnn dst port 80-c1000|awk -F"."'{print $1"."$2"."$3"."$4}'|sort|uniq-c|sort-nr|head-20

# 更精确的方式(处理 IPv4)
tcpdump -i eth0 -tnn dst port 80-c1000|awk -F"[ :]"'{print $1}'|sort|uniq-c|sort-nr|head-20

4. 查找较多 TIME_WAIT 连接

# 传统方式
netstat-n|grep TIME_WAIT |awk'{print $5}'|sort|uniq-c|sort-rn|head-n20

# 现代方式
ss -ant state time-wait |awk'NR>1 {split($5,a,":"); print a[1]}'|sort|uniq-c|sort-rn|head-n20

5. 查找较多的 SYN 连接(SYN Flood 攻击检测)

# 传统方式
netstat-an|grep SYN |awk'{print $5}'|awk -F: '{print $1}'|sort|uniq-c|sort-nr|head-20

# 现代方式
ss -ant state syn-sent |awk'NR>1 {split($5,a,":"); print a[1]}'|sort|uniq-c|sort-rn|head-20
ss -ant state syn-recv |awk'NR>1 {split($5,a,":"); print a[1]}'|sort|uniq-c|sort-rn|head-20

6. 根据端口查找进程

# 传统方式
netstat-ntlp|grep80|awk'{print $7}'|cut -d/ -f1

# 现代方式(推荐)
ss -ntlp|grep':80'|awk'{print $6}'|cut -d, -f2|cut-d=-f2

# 更直接的方式
lsof-i :80
fuser80/tcp

二、网站日志分析篇(Apache/Nginx 通用)

1. 获得访问前 10 位的 IP 地址

# Apache 标准日志格式
cat access.log |awk'{print $1}'|sort|uniq-c|sort-nr|head-10

# 更高效的单遍处理方式
awk'{counts[$1]++} END {for(ip in counts) print counts[ip], ip}' access.log |sort-nr|head-10

# 排除已知爬虫/静态资源(可选)
awk'$1 !~ /^(127\.0\.0\.1|::1)/ {counts[$1]++} END {for(ip in counts) print counts[ip], ip}' access.log |sort-nr|head-10

2. 访问次数最多的文件或页面(取前 20)

# 注意:原命令中的 $11 是 Apache 日志中的 referer,若要统计请求的 URL 应使用 $7
cat access.log |awk'{print $7}'|sort|uniq-c|sort-nr|head-20

# 排除静态资源,只看动态页面
cat access.log |awk'$7 ~ /\.(php|jsp|asp|py|cgi)/ {print $7}'|sort|uniq-c|sort-nr|head-20

3. 列出传输最大的几个文件(分析下载站常用)

# 原命令(.exe 文件)
cat access.log |awk'($7~/\.exe/){print $10, $1, $4, $7}'|sort-nr|head-20

# 扩展:常见可下载文件类型
cat access.log |awk'($7~/\.(exe|zip|rar|tar\.gz|pdf|mp4|apk|dmg)/){print $10, $1, $4, $7}'|sort-nr|head-20

4. 列出大于 200KB 的下载文件及发生次数

cat access.log |awk'($10 > 200000 && $7~/\.exe/){print $7}'|sort|uniq-c|sort-nr|head-100

# 更友好的输出(转换为 KB/MB)
cat access.log |awk'($10 > 200000 && $7~/\.exe/){size[$7]+=$10; count[$7]++} END {for(f in count) printf "%d次\t%.2fMB\t%s\n", count[f], size[f]/1024/1024, f}'|sort-k3-nr|head-100

5. 最耗时的页面(假设日志最后一列为响应时间,单位秒)

# 原命令(假设响应时间在最后一列)
cat access.log |awk'($7~/\.php/){print $NF, $1, $4, $7}'|sort-nr|head-100

# 更精确的 Nginx/Apache 通用方式(需确认日志格式)
# 如果日志格式为:$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time
cat access.log |awk'{print $NF, $1, $4, $7}'|sort-nr|head-100

6. 列出超过 60 秒的页面及发生次数

cat access.log |awk'($NF > 60 && $7~/\.php/){print $7}'|sort|uniq-c|sort-nr|head-100

# 带平均响应时间的统计
cat access.log |awk'($NF > 60 && $7~/\.php/){count[$7]++; sum[$7]+=$NF} END {for(url in count) printf "%d次\t平均%.2fs\t%s\n", count[url], sum[url]/count[url], url}'|sort-nr|head-100

7. 列出传输时间超过 30 秒的文件

cat access.log |awk'($NF > 30){print $7}'|sort|uniq-c|sort-nr|head-20

8. 统计网站流量(GB)

# 原命令
cat access.log |awk'{sum+=$10} END {print sum/1024/1024/1024 " GB"}'

# 更友好的输出
cat access.log |awk'{sum+=$10} END {printf "总流量: %.2f GB (%.2f MB)\n", sum/1024/1024/1024, sum/1024/1024}'

# 按天统计流量
cat access.log |awk'{gsub(/\//," ",$4); split($4,a,":"); day=a[1]" "a[2]" "a[3]; traffic[day]+=$10} END {for(d in traffic) printf "%s\t%.2f MB\n", d, traffic[d]/1024/1024}'|sort

9. 统计 404 错误

# 原命令
awk'($9 ~/404/)' access.log |awk'{print $9, $7}'|sort

# 更高效的方式
awk'$9 == 404 {print $9, $7}' access.log |sort|uniq-c|sort-nr

# 统计 404 并按 IP 分组
awk'$9 == 404 {counts[$1" "$7]++} END {for(i in counts) print counts[i], i}' access.log |sort-nr|head-20

10. 统计 HTTP 状态码

# 方式一:关联数组
cat access.log |awk'{counts[$9]++} END {for(code in counts) print code, counts[code]}'

# 方式二:管道组合
cat access.log |awk'{print $9}'|sort|uniq-c|sort-rn

# 带百分比的状态码分布
cat access.log |awk'{counts[$9]++; total++} END {for(code in counts) printf "%s\t%d\t%.2f%%\n", code, counts[code], counts[code]/total*100}'|sort-rn

11. 蜘蛛/爬虫分析

# 原命令(tcpdump 方式,实时分析)
/usr/sbin/tcpdump -i eth0 -l-s0-w - dst port 80| strings |grep-i user-agent |grep-i-E'bot|crawler|slurp|spider'

# 更实用的日志分析方式
cat access.log |awk -F'"''{print $6}'|grep-i-E'bot|crawler|slurp|spider|bingpreview'|sort|uniq-c|sort-rn|head-20

# 按蜘蛛类型和访问页面统计
cat access.log |awk -F'"''{ua=$6; url=$2} ua ~ /bot|crawler|spider/i {split(ua,a," "); spider[a[1]]++; pages[url]++} END {print "=== 蜘蛛类型 ==="; for(s in spider) print spider[s], s; print "\n=== 热门爬取页面 ==="; for(p in pages) print pages[p], p}'|head-30

三、Squid 代理日志分析

按域统计流量

# 原命令
zcat squid_access.log.tar.gz |awk'{print $10,$7}'|awk'BEGIN{FS="[ /]"}{trfc[$4]+=$1}END{for(domain in trfc){printf "%s\t%d\n",domain,trfc[domain]}}'

# 优化版本(更清晰的输出,转换为 MB)
zcat squid_access.log.tar.gz |awk'{trfc[$7]+=$10} END {for(url in trfc) {split(url,a,"/"); domain=a[3]; if(domain=="") domain=a[1]; domain_trfc[domain]+=trfc[url]} for(d in domain_trfc) printf "%s\t%.2f MB\n", d, domain_trfc[d]/1024/1024}'|sort-k2-nr|head-20

四、系统 Debug 分析篇

1. 调试命令 - strace

# 跟踪正在运行的进程
strace-p<pid>

# 跟踪系统调用并统计
strace-c-p<pid>

# 跟踪文件操作(查看进程在读写哪些文件)
strace-etrace=file -p<pid>

# 跟踪网络相关调用
strace-etrace=network -p<pid>

# 输出到文件
strace-o /tmp/strace.log -p<pid>

# 跟踪子进程
strace-f-p<pid>

2. 跟踪指定进程的 PID - gdb

# 附加到运行中的进程
gdb -p<pid>

# 常用 gdb 调试命令
(gdb) bt              # 查看调用栈
(gdb) info threads    # 查看线程信息
(gdb) thread apply all bt  # 查看所有线程的调用栈
(gdb) info registers  # 查看寄存器
(gdb) call function()# 调用函数
(gdb) detach          # 分离进程
(gdb) quit            # 退出

快速诊断脚本模板

#!/bin/bash
# web_server_check.sh - Web 服务器快速诊断脚本

echo"========== 系统连接状态 =========="
ss -s

echo-e"\n========== TCP 各状态连接数 =========="
ss -ant|awk'NR>1 {print $1}'|sort|uniq-c|sort-rn

echo-e"\n========== 80 端口连接最多的 IP(Top 10)=========="
ss -ant|awk'/:80/ && NR>1 {split($5,ip,":"); ++A[ip[1]]} END {for(i in A) print A[i], i}'|sort-rn|head-10

echo-e"\n========== 当前 ESTABLISHED 连接数 =========="
ss -ant state established |wc-l

echo-e"\n========== TIME_WAIT 连接数 =========="
ss -ant state time-wait |wc-l

echo-e"\n========== 监听端口 =========="
ss -tlnp

echo-e"\n========== 系统负载 =========="
uptime

echo-e"\n========== 内存使用 =========="
free-h

echo-e"\n========== 磁盘使用 =========="
df-h

echo-e"\n========== Nginx/Apache 进程 =========="
ps aux |grep-E'nginx|apache|httpd'|grep-vgrep

最新文章

随机文章