跳转至

Shell 运维组合案例

下面案例重点展示分析顺序。字段位置必须以现场命令输出和日志格式为准,不要直接复制后假设所有系统一致。

HTTP 状态码统计

假设 Nginx combined log 的状态码是第 9 字段:

awk '{count[$9]++}
     END {for (code in count) print count[code], code}' access.log \
  | sort -nr

先抽样确认字段:

head -1 access.log
awk 'NR==1 {for (i=1; i<=NF; i++) print i, $i}' access.log

日志格式变化后第 9 字段可能不再是状态码,生产最好输出 JSON 并用结构化工具处理。

访问最多的客户端 IP

awk '{print $1}' access.log \
  | sort \
  | uniq -c \
  | sort -nr \
  | head -20

反向代理场景 $1 可能是 LB 地址,真实客户端取决于可信代理和日志中的 X-Forwarded-For 处理;不能仅凭结果封禁 IP。

TCP 连接状态

ss -ant \
  | awk 'NR>1 {state[$1]++}
         END {for (key in state) print state[key], key}' \
  | sort -nr

查看远端连接最多的地址时要先确认 ss 输出列和 IPv6 格式。简单按冒号切割会把 IPv6 地址拆坏。

进程 CPU 和内存 Top N

ps -eo pid,ppid,user,%cpu,%mem,rss,etime,cmd --sort=-%cpu | head -20
ps -eo pid,ppid,user,%cpu,%mem,rss,etime,cmd --sort=-rss  | head -20

ps --sort 是 GNU/procps 常用能力,macOS/BSD 参数不同。瞬时 CPU 只用于定位候选,还要结合持续采样、线程、应用指标和最近变更。

文件系统使用率告警候选

df -P \
  | awk 'NR>1 {
      used=$5
      sub(/%$/, "", used)
      if (used >= 80) print used "%", $6
    }' \
  | sort -nr

挂载点包含空格时字段处理会复杂;自动化监控优先使用稳定指标采集,而不是周期性解析人类可读命令。

日志错误 Top N

grep -E 'ERROR|Exception|timeout|connection refused' app.log \
  | sed -E 's/request_id=[^ ]+/request_id=<id>/g' \
  | sort \
  | uniq -c \
  | sort -nr \
  | head -20

如果每行含时间、线程和随机 ID,必须先归一化动态字段,否则每行都不同,uniq -c 没有意义。归一化也可能把不同错误合并,最终仍需查看原始上下文和堆栈。

按时间范围查看 systemd 日志

journalctl -u app.service \
  --since '2026-08-24 10:00:00' \
  --until '2026-08-24 10:30:00' \
  --no-pager \
  | grep -Ei 'error|exception|timeout'

这里 grep -E 替代旧的 egrep-i 忽略大小写。先确认主机和日志时区再与告警时间对应。

安全修改配置

cp -a app.conf "app.conf.bak.$(date +%Y%m%d%H%M%S)"
sed 's/^log_level=.*/log_level=INFO/' app.conf > app.conf.new
diff -u app.conf app.conf.new
appctl check-config app.conf.new
mv app.conf.new app.conf
systemctl reload app
systemctl status app --no-pager

关键顺序是备份、生成新文件、查看差异、语法检查、替换、reload、运行验证。sed -i 只能缩短命令,不能替代变更验证和回滚。

查找大日志

find /var/log -xdev -type f -size +100M -print0 \
  | xargs -0 du -h \
  | sort -h

-xdev 限制在当前文件系统,NUL 分隔安全处理带空格文件名。发现大日志后应修复轮转和日志量,不要在进程仍持有文件时直接删除;已删除但空间未释放可用 lsof +L1 检查。

拆开验证流水线

复杂命令应逐段检查:

grep -E 'ERROR|timeout' app.log | head
grep -E 'ERROR|timeout' app.log | sed -E '...' | head
grep -E 'ERROR|timeout' app.log | sed -E '...' | sort | uniq -c | head

每加入一段就确认输入、输出和行数,能快速发现正则不匹配、字段位置错误、locale 排序或过度归一化。