Shell 六件套:curl / awk / grep / sed / sort / uniq 运维实战指南
Shell 六件套:curl / awk / grep / sed / sort / uniq 运维实战指南
本文系统梳理 Linux 运维中最核心的六个命令,涵盖基本用法、常用参数和实战排查场景。
一、curl — HTTP 请求工具
简介
curl 是一个利用 URL 语法传输数据的命令行工具,支持 HTTP/HTTPS/FTP 等多种协议。在运维中主要用于接口调试、健康检查、数据拉取。
基础语法
Bash
curl [选项] URL
常用参数
| 参数 | 说明 |
|---|---|
-X / --request |
指定请求方法(GET POST PUT DELETE) |
-H / --header |
添加请求头 |
-d / --data |
发送 POST 数据(自动设 Content-Type: application/x-www-form-urlencoded) |
-b / --cookie |
携带 Cookie |
-i / --include |
输出包含响应头 |
-I / --head |
只获取响应头(HEAD 请求) |
-o / --output |
将响应写入文件 |
-s / --silent |
静默模式(不显示进度条和错误) |
-S / --show-error |
与 -s 搭配,只显示错误 |
-v / --verbose |
显示详细通信过程 |
-k / --insecure |
跳过 SSL 证书验证 |
-L / --location |
跟随重定向 |
-w / --write-out |
输出额外信息(如状态码、耗时) |
--connect-timeout |
连接超时时间(秒) |
--max-time |
整个请求最大时间(秒) |
-u / --user |
指定 Basic Auth 用户名密码 |
常见用法
Bash
# GET 请求
curl http://api.example.com/health
# 查看响应头
curl -I https://example.com
# POST JSON 数据
curl -X POST -H "Content-Type: application/json" \
-d '{"name":"test","status":"ok"}' \
http://api.example.com/create
# 带 Cookie 请求
curl -b "session=abc123" http://api.example.com/profile
# 查看请求详细过程(调试神器)
curl -v https://example.com
# 仅输出状态码(配合监控告警)
curl -s -o /dev/null -w "%{http_code}" https://example.com
# 测量请求耗时
curl -s -o /dev/null -w "\nHTTP Code: %{http_code}\n\
DNS Time: %{time_namelookup}s\n\
Connect Time: %{time_connect}s\n\
SSL Time: %{time_appconnect}s\n\
TTFB: %{time_starttransfer}s\n\
Total Time: %{time_total}s\n" https://example.com
二、awk — 文本分析与格式化
简介
awk 是一个强大的文本处理语言,擅长按列处理结构化文本。它逐行读取输入,按分隔符拆分为字段,然后执行指定的操作。在运维中常用于日志分析、报表生成、数据提取。
基础语法
Bash
awk [选项] '条件 {动作}' 文件
核心概念
内置变量:
| 变量 | 说明 |
|---|---|
$0 |
整行内容 |
$1, $2, ... |
第 1、2... 个字段 |
NF |
当前行的字段数($NF 取最后一个字段) |
NR |
已处理的行号 |
FS |
字段分隔符(默认空格/制表符,可用 -F 指定) |
OFS |
输出字段分隔符 |
RS |
行分隔符 |
ORS |
输出行分隔符 |
常用参数
| 参数 | 说明 |
|---|---|
-F |
指定字段分隔符(如 -F, 处理 CSV) |
-v |
设置变量(如 -v var=value) |
-f |
从脚本文件读取 awk 程序 |
常见用法
Bash
# 打印第 1 列和第 3 列
awk '{print $1, $3}' file.txt
# 指定分隔符(以冒号分隔)
awk -F: '{print $1, $3}' /etc/passwd
# 条件过滤(打印第 3 列大于 100 的行)
awk '$3 > 100 {print $0}' data.txt
# 行号过滤(打印第 10 到 20 行)
awk 'NR >= 10 && NR <= 20' file.txt
# BEGIN 和 END 块(先执行初始化,结束后执行汇总)
awk 'BEGIN {sum=0} {sum+=$3} END {print "Total:", sum}' data.txt
# 格式化输出
awk '{printf "%-20s %5d\n", $1, $2}' file.txt
常用内置函数
Bash
length($0) # 字符串长度
substr($1, 1, 3) # 子串(从第1位取3个字符)
index(str, "x") # 返回子串位置
split($1, arr, ",") # 分割字符串到数组
gsub(/old/, "new") # 全局替换
match($0, /pattern/) # 正则匹配
tolower($1) / toupper($1) # 大小写转换
三、grep — 文本搜索
简介
grep 用于搜索文件中匹配指定模式的行,是日志排查使用频率最高的命令。
基础语法
Bash
grep [选项] 模式 [文件...]
常用参数
| 参数 | 说明 |
|---|---|
-i |
忽略大小写 |
-v |
反向匹配(显示不包含模式的行) |
-n |
显示匹配行的行号 |
-c |
统计匹配行数 |
-l |
只显示包含匹配的文件名 |
-L |
只显示不包含匹配的文件名 |
-r 或 -R |
递归搜索目录 |
-w |
按单词搜索(精确匹配) |
-x |
按整行匹配 |
-A N |
显示匹配行后的 N 行(After) |
-B N |
显示匹配行前的 N 行(Before) |
-C N |
显示匹配行前后各 N 行(Context) |
-e |
指定多个模式(grep -e "err" -e "warn") |
-E |
使用扩展正则表达式(等价于 egrep) |
-P |
使用 Perl 兼容正则(性能更好) |
-o |
只显示匹配的部分(而非整行) |
--color |
高亮显示匹配(通常默认开启) |
常见用法
Bash
# 基础搜索
grep "ERROR" app.log
grep -n "ERROR" app.log # 带行号
grep -i "error" app.log # 忽略大小写
grep -c "ERROR" app.log # 计数
# 上下文
grep -C 5 "OutOfMemory" app.log # 前后各 5 行
grep -A 10 "Stack Trace:" app.log # 后面 10 行
grep -B 3 "Exception" app.log # 前面 3 行
# 递归搜索
grep -r "function_name" src/
# 多模式
grep -e "ERROR" -e "FATAL" app.log
# 排除
grep -v "^#" config.yaml # 去掉注释行
grep -v "^$" file.txt # 去掉空行
# 提取匹配部分
echo "time=123ms level=error" | grep -oP 'time=\K\d+'
# → 123
四、sed — 流式文本编辑器
简介
sed(Stream Editor)是非交互式的文本编辑工具,逐行处理输入,支持替换、删除、插入操作。适合批量文本替换、配置文件修改、日志预处理。
基础语法
Bash
sed [选项] '命令' 文件
常用参数
| 参数 | 说明 |
|---|---|
-n |
取消默认输出,只打印被 p 处理的行 |
-i |
直接修改文件;-i.bak 备份后修改 |
-e |
指定多条命令 |
-r / -E |
扩展正则表达式 |
-f |
从脚本文件读取命令 |
核心命令
| 命令 | 说明 |
|---|---|
s/old/new/ |
替换 |
s/old/new/g |
全局替换 |
p |
打印行 |
d |
删除行 |
q |
退出 |
i\text |
在当前行前插入 |
a\text |
在当前行后追加 |
c\text |
替换整行 |
y/abc/ABC/ |
字符映射 |
行寻址
Bash
sed -n '3p' file # 打印第 3 行
sed -n '2,5p' file # 打印第 2 到 5 行
sed -n '/error/p' file # 打印匹配 error 的行
sed -n '/start/,/end/p' file # 打印 start 到 end 之间的行
sed '1~2d' file # 删除奇数行
常见用法
Bash
# 文件内替换(直接修改)
sed -i 's/192.168.1.1/10.0.0.1/g' config.ini
# 删除空行和注释
sed -i '/^$/d; /^#/d' config.yaml
# 在匹配行前后插入
sed '/listen 80/i\listen 443 ssl;' nginx.conf # 前插
sed '/server_name/a\ return 301 https://$host$request_uri;' nginx.conf # 后插
# 行范围提取
sed -n '/^\[database\]/,/^\[/p' config.ini # 提取 database 配置段
五、sort — 排序
简介
sort 对文本行按指定规则排序。注意默认是字典序,数字排序需加 -n。
常用参数
| 参数 | 说明 |
|---|---|
-n |
按数字排序(重要!默认是字典序) |
-r |
倒序 |
-u |
去重(等价于 sort | uniq) |
-k N |
按第 N 列排序 |
-t X |
指定字段分隔符 |
-h |
按人类可读大小排(2K < 1M < 2G) |
-M |
按月份排(JAN < FEB < ... < DEC) |
-V |
版本号排序 |
-c |
检查是否已排序 |
-R |
随机排序 |
-o 文件 |
写入文件(可覆盖自身) |
完整演示
Bash
# 默认字典序 vs 数字排序
printf "1\n2\n10\n" | sort # → 1, 10, 2
printf "1\n2\n10\n" | sort -n # → 1, 2, 10
# 按列排序
sort -k 3 -n scores.txt # 按第 3 列数字排
sort -t: -k 3 -n /etc/passwd # 按 UID 排
# 多级排序
sort -k 2,2 -k 3,3nr data.txt # 先按第2列,再按第3列数字倒序
# 文件大小排序
ls -lh | sort -k 5 -h -r # 文件按大小倒序
六、uniq — 去重与计数
简介
uniq 用于从已排序文本中检测/删除重复行和统计出现次数。重要前提:只处理相邻行,通常需要先 sort。
常用参数
| 参数 | 说明 |
|---|---|
-c |
在行前显示出现次数 |
-d |
只显示重复行(出现 >= 2 次) |
-D |
显示所有重复行的完整内容 |
-u |
只显示唯一行(只出现 1 次) |
-i |
忽略大小写 |
-f N |
比较时跳过前 N 个字段 |
-s N |
比较时跳过前 N 个字符 |
常见用法
Bash
sort data.txt | uniq -c # 统计频次
sort data.txt | uniq -d # 只显示重复项
sort data.txt | uniq -u # 只显示唯一项
sort data.txt | uniq -c | sort -rn # 频次降序排(经典组合)
七、运维排查实战场景
场景 1:分析 Nginx 访问日志
Bash
# 统计访问量最高的 10 个 IP
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -10
# 统计 HTTP 状态码分布
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 统计请求最多的 10 个 URL
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -10
# 统计请求耗时 > 3s 的慢请求
awk '{sub(/\"/, "", $NF); if ($NF > 3) print $7, $NF}' access.log | sort -k2 -rn
# 分析 500 错误的来源 IP
grep ' "500 ' access.log | awk '{print $1}' | sort | uniq -c | sort -rn
场景 3:磁盘 / 内存排查
Bash
# 查看各目录占用大小(人类可读),按大小排
du -sh /* 2>/dev/null | sort -rh | head -10
# 查看 TOP 10 大文件
find / -type f -size +100M 2>/dev/null -exec ls -lh {} \; | sort -k5 -h -r | head -10
# 查看各进程内存占用(排序)
ps aux | sort -k4 -rn | head -10
# 查看各进程 CPU 占用(排序)
ps aux | sort -k3 -rn | head -10
场景 3:配置文件批量修改
Bash
# 批量修改 Nginx 端口 80 → 443
sed -i 's/listen 80;/listen 443 ssl;/g' /etc/nginx/sites-enabled/*
# 批量替换数据库连接串
sed -i 's/jdbc:mysql:\/\/old-host/jdbc:mysql:\/\/new-host/' *.properties
# 提取配置文件某一段
sed -n '/^\[mysqld\]/,/^\[/p' /etc/mysql/my.cnf | head -n -2
场景 4:接口健康检查脚本
Bash
#!/bin/bash
# API 健康检查
URL="http://api.example.com/health"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "$URL")
if [ "$HTTP_CODE" != "200" ]; then
echo "CRITICAL: API returned $HTTP_CODE"
exit 2
fi
# 检查响应内容
RESPONSE=$(curl -s "$URL")
STATUS=$(echo "$RESPONSE" | grep -oP '"status"\s*:\s*"\K[^"]+')
if [ "$STATUS" != "healthy" ]; then
echo "CRITICAL: API status is $STATUS"
exit 2
fi
echo "OK: API is healthy"
exit 0
场景 5:日志实时监控报警
Bash
# 实时监控日志中的错误
tail -f app.log | grep --line-buffered "ERROR\|CRITICAL\|FATAL"
# 5 分钟内错误数量激增检测
tail -n 10000 app.log | awk -v date="$(date -d '5 min ago' '+%H:%M')" \
'$0 ~ date && /ERROR/ {count++} END {print count; if (count > 50) exit 1}'
# 可组合的监控管道
tail -f access.log | awk '{
if ($9 ~ /5[0-9][0-9]/) {
print strftime("%Y-%m-%d %H:%M:%S"), $1, $7, $9
}
}'
场景 6:数据汇总与报表
Bash
# 按小时统计 PV
awk '{print $4}' access.log | cut -d: -f2 | sort | uniq -c | sort -rn
# 统计各 API 端点的平均响应时间
awk '{
url=$7; time=$NF
gsub(/\"/, "", time)
total[url] += time
count[url]++
}
END {
for (url in total) {
printf "%-50s %.2fs %d次\n", url, total[url]/count[url], count[url]
}
}' access.log | sort -k2 -rn | head -20
# 统计各 IP 的请求字节数
awk '{bytes[$1] += $10} END {for (ip in bytes) print ip, bytes[ip]}' access.log | sort -k2 -rn
八、命令速查卡片
快速参考
Bash
# grep — 一切从搜索开始
grep -n "keyword" file # 搜索并显示行号
grep -rli "keyword" dir/ # 递归搜索,只显示文件名
grep -C 5 "pattern" file # 带上下文
# awk — 按列处理
awk '{print $1, $NF}' file # 打印首列和末列
awk -F: '$3 > 1000' /etc/passwd # 过滤
awk '{sum+=$1} END{print sum}' # 求和
# sed — 批量替换
sed -i 's/old/new/g' file # 全局替换
sed -i.bak 's/x/y/' file # 备份后替换
sed -n '/start/,/end/p' file # 范围提取
# sort + uniq — 统计组合
sort file | uniq -c | sort -rn # 频次统计(三板斧)
# curl — 接口调试
curl -s -o /dev/null -w "%{http_code}" url # 只看状态码
curl -v url # 看完整通信过程
记忆口诀
grep 搜索靠模式 awk 按列好处理
sed 替换批量做 sort 排序记加 n
uniq 去重要排序 curl 调接口全搞定
组合起来六件套 日志排查不慌张