那是三年前的一个深夜,我们负责的一个电商平台突然出现用户登录异常。监控数据显示,某个微服务的日志文件在短短五分钟内膨胀到了2GB。我打开日志文件一看,密密麻麻的错误信息让人头皮发麻。当时团队里有人提议用Python写个脚本分析,但等脚本写好,黄花菜都凉了。我二话不说,掏出三剑客,三下五除二就定位到了问题根源——某个上游服务的超时设置被误修改了。
grep:日志分析的第一道防线
那次事故让我意识到,grep不是简单的文本搜索工具,而是运维人员的“侦察兵”。比如,当我们需要从海量日志中找出所有包含“ERROR”的行,同时排除“heartbeat”这种常规心跳日志时,我会这样操作:
grep -E "ERROR|FATAL" app.log | grep -v "heartbeat" | grep -v "healthcheck"
这里-E表示使用扩展正则表达式,-v表示排除匹配的行。但更高级的用法是结合-A、-B和-C参数查看上下文:
grep -B 5 -A 10 "OutOfMemoryError" app.log
这个命令会显示匹配行前5行和后10行的内容,对于分析OOM(内存内存异常)的调用栈特别有用。有一次,我就是通过这种方式发现了一个定时任务没有释放数据库连接池的bug。
sed:批量文本替换的瑞士军刀
sed在我手中最常用的场景是批量修改设置文件。记得有一次,我们需要将线上所有Nginx设置中的worker_processes从4改为8,涉及200多台服务器。如果手动改,估计要改到天亮。
我的做法是先写一个sed脚本:
sed -i 's/^worker_processes.*$/worker_processes 8;/' /etc/nginx/nginx.conf
-i参数表示直接修改文件,s是替换命令。但这里有个坑——如果设置文件中worker_processes后面有空格或注释,直接替换可能会出问题。所以我通常会先备份:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%Y%m%d)
sed -i 's/^worker_processes[[:space:]]*[0-9]\+;/worker_processes 8;/' /etc/nginx/nginx.conf
[[:space:]]*匹配任意数量的空白字符,[0-9]\+匹配一个或多个数字。这样就能精确匹配到设置项,不会误伤其他内容。
awk:结构化数据处理的利器
awk是我认为三剑客中最强大的工具,尤其适合处理表格化的日志数据。比如我们有一个Nginx访问日志,格式是:
192.168.1.1 - - [10/Oct/2023:13:55:36 +0800] "GET /api/user HTTP/1.1" 200 1234
要统计每个接口的访问次数和平均响应时间,用awk可以轻松搞定:
awk '{split($7, path, "?"); url=path[1]; status=$9; size=$10}
status==200 {count[url]++; total[url]+=size}
END {for (url in count) print url, count[url], int(total[url]/count[url])}' access.log | sort -k2 -rn | head -10
这里$7是请求路径,split函数去掉查询参数,$9是状态码,$10是响应大小。最后用sort按访问次数降序排列,取前10个接口。这个命令帮我们快速定位到哪些接口的响应体过大,需要优化。
三剑客联合作战
真正的威力在于组合使用。有一次,我们需要从几十GB的日志中找出某个时间段内,所有调用支付接口且状态码为500的请求,并统计每个用户的失败次数。我用了这样一个管道:
grep "pay/create" app.log | awk '$4 ~ /^\[10\/Oct\/2023:1[3-4]/ && $9 == 500' | awk '{print $1}' | sort | uniq -c | sort -rn | head -20
第一层grep筛选出支付接口的日志,第二层awk用正则匹配时间范围(13点到14点)和状态码,第三层awk提取用户IP,最后用sort和uniq统计每个IP的失败次数。整个过程不到30秒,就定位到了某个异常IP在疯狂重试。
实战中的几个坑
-
sed的-i参数在不同系统上行为不同:Linux上直接修改文件,macOS上需要加空参数sed -i ''。我建议在脚本中统一使用sed -i.bak,这样既保留备份又跨平台兼容。
-
awk的字段分隔符:默认是空白字符,但日志中经常用逗号或竖线分隔。记得用-F指定,比如awk -F',' '{print $1}'。
-
正则表达式的转义:在grep中使用\转义特殊字符时,注意单引号和双引号的区别。建议统一用单引号包裹正则表达式,避免shell变量展开。
-
大文件处理:对于GB级别的文件,grep和awk都支持流式处理,不会把整个文件加载到内存。但sort命令会,所以尽量在管道最后使用sort,或者用sort -S 1G控制内存使用。
-
写在最后
三剑客虽然看起来简单,但真正用好需要大量实践。我建议运维新手从日常日志分析开始练手,比如统计某个接口的响应时间分布、找出异常IP、批量修改设置等。当你能熟练组合使用这三个工具时,你会发现很多看似复杂的问题,其实一行命令就能解决。
记住,工具只是手段,解决问题才是目的。三剑客的价值不在于它们有多炫酷,而在于它们能帮你快速定位问题、恢复服务。这,才是运维工程师的核心竞争力。
👨💻 运维经验:根据实际生产环境,以上步骤建议先在测试环境验证,并做好备份。参数值需根据服务器设置调整,不要盲目照搬。