凌晨三点,手机震动。我摸黑爬起来,屏幕上显示“生产环境访问异常”的告警。那种心跳加速的感觉,做过运维的都懂。但这次,我已经从运维岗转到了安全方向,手里的工具没变,变的只是看问题的角度。日志就在那,几百万行躺着,静悄悄地记录了一切。关键是你知不知道看哪里、怎么看。很多人一听“安全分析”就觉得是高大上的 SIEM 平台、复杂的攻击链还原,其实真到了应急响应那一刻,先用顺手的反而是最朴素的几个 Linux 命令。我转安全这几年,最深的体会是:那些年在运维岗上天天用的基本功,一样都没有浪费。这篇文章我就聊聊自己从运维转安全后,用的最多的 5 个日志分析命令 — grep、awk、sed、sort、uniq,以及它们到底怎么在安全排查里组合起来干活。适合正在考虑转安全的运维朋友、刚入门的安全新人,也适合那些觉得日志分析很玄乎、想从实操入手的同学。看完你会发现,转型的第一步不是学新东西,而是把已经会的东西换个思路用。1. 为什么日志分析是运维转安全的第一站1.1 日志在运维眼里是告警,在安全眼里是案发现场做运维的时候,我看日志是为了回答三个问题:系统为什么慢了?服务为什么挂了?磁盘为什么满了?那时候日志是排障工具,只要把错误信息捞出来、定位到具体模块,任务就算完成。转了安全之后,同样一份日志,要回答的问题完全变了——谁进来了?怎么进来的?进来之后干了什么?已经走了还是还在?同样是看/var/log/secure,运维关心的是“哪个用户登录失败了”,安全关心的是“同一个 IP 在五分钟内试了一百次密码,是不是在爆破”。这种视角的转换,不需要把 Linux 推倒重学。恰恰相反,用的还是那套管道符、重定向、正则表达式。日志分析本质上是文本处理,安全日志和业务日志在格式上没有本质区别,区别只在于你要从里面提取什么信号。1.2 为什么先学组合命令,而不是直接上安全分析平台有些朋友上来就研究各种复杂的日志分析平台、可视化大屏,我觉得顺序反了。平台是辅助,底层能力才是核心。原因有几个:第一,应急响应往往发生在客户现场或者老旧的跳板机上,环境简陋到什么程度都不奇怪,可能连包管理器都不让你装。这时候你总不能说“等我搭个平台再排查吧”。手里有 Bash,就什么都不慌。第二,安全分析平台展示的告警、趋势图,底层逻辑依然是筛选、聚合、排序、统计。搞懂 grep 怎么做条件过滤、awk 怎么做字段提取、sort 和 uniq 怎么做排序去重,再用任何平台都能一眼看穿它背后的查询逻辑,不会被参数和图表带偏。第三,日志分析不是一次性的动作,而是一个反复迭代的过程。你可能要先快速筛一遍看有没有明显特征,再深入提取数据,再换个维度重新看。这种快速试错的节奏,靠命令行管道是最舒服的,改一个参数、加一个条件,立刻就能跑出新结果。1.3 五个命令的分工与协作关系我给自己总结过一个非常朴素的日志分析流水线:先缩小范围,再拆解字段,然后排序、去重、计数,最后得出结论。五个命令正好对应这条流水线的五个环节。grep 负责条件过滤,像一道筛子,把几百万行日志里符合条件的行捞出来。awk 负责字段拆解和统计,把日志行按空格或逗号切开,提取 IP、状态码、耗时这些关键信息,还能直接做累加计数。sed 负责区间截取和文本变形,在大量日志里切出特定时间窗口的内容,或者做敏感信息脱敏。sort 负责排序,让数据从杂乱无章变成有规律可循。uniq 负责去重和计数,配合 sort 使用,能快速找出“哪个 IP 最活跃”、“哪种攻击特征出现最多”。单个命令都很简单,难的是把它们串起来。管道符加起来的战斗力,远超任何一个命令单独使用的效果。下面我按自己在真实排查里用得最多的场景,把这五个命令逐一拆开讲清楚。2. grep:安全日志的第一道筛子2.1 从一次网站被刷说起去年帮某客户排查一次网站访问异常。客户的反馈是首页响应很慢,打开要十几秒。按运维思维先查负载、查连接数,指标看着都还算正常,但业务就是卡。后来我去翻了 nginx 的 access.log,先用 grep 做了个很简单的过滤:grep -c "HTTP/1.1\" 502" /var/log/nginx/access.log执行完我就有点数了:过去一小时里 502 出现了两千多次,正常情况下这个数字应该是几十。网站的故障表象是慢,但真正的异常逻辑藏在日志的这列状态码里。这就是我要说的第一件事:grep 是最基础的筛选工具,但它在安全分析里的用法,和运维排障时不完全一样。运维通常用 grep 找某个明确的错误关键字,比如grep "OutOfMemory"。而安全分析时,你要筛的往往不是“确定发生了什么”,而是“有没有我没见过的异常迹象”,所以反过来,我更多用 grep 去“排除”噪音,把正常的请求过滤掉,剩下的就是可疑的东西。2.2 安全场景里真正有用的几个 grep 用法基础语法我就不啰嗦了,grep [选项] 模式 文件。我重点说几个实战里高频用到的选项。第一个是-E,扩展正则。在 access.log 里分析可疑扫描行为时,经常要同时匹配多个特征。比如想筛出所有访问路径里带admin、manager、phpmyadmin的请求,一句话就搞定:grep -E "/admin|/manager|/phpmyadmin" /var/log/nginx/access.log | head -100第二个是-v,反向匹配。健康检查、监控探针这类请求会污染分析结果,每次都得先踢掉它们:grep -v -E "User-Agent: (ELB-HealthChecker|kube-probe)" /var/log/nginx/access.log第三个是-c,统计数量。不要一上来就全量看内容,先计数,数量异常本身就是信号。比如想看某台机器上 sshd 登录失败的次数,直接:grep -c "Failed password" /var/log/secure2.3 一个必须养成的习惯:IP 匹配一定要加边界这个坑我踩过好几次。比如你想筛来自某个 IP 的请求,直接写grep "192.168.1.100",可能会把192.168.1.1000、192.168.1.1001这种根本不存在的地址也带进来,更麻烦的是会把192.168.1.100.5这类畸形请求混进来。因为 grep 是子串匹配,它不管字符前后是什么。正确姿势是给 IP 加上边界,保证匹配到的是完整的地址:grep -E "(^|[^0-9.])192\.168\.1\.100([^0-9.]|$)" /var/log/nginx/access.log看着麻烦,但这条命令的价值在于:当你把可疑 IP 的特征写到告警规则、写到自动化脚本里时,不会因为草率匹配产生大量误报。运维阶段的教训是“日志里有噪音分析不出结果”,安全阶段的教训是“误报太多,真正告警就没人在意了”。2.4 我的实操建议:把 grep 特征写成清单用 grep 做安全分析,最大的忌讳是每次都在命令行里临时编正则,想到一个写一个,结果反复敲一长串。我会把常用的筛选用法沉淀成一个小脚本,或者直接写成 grep 特征清单文件,一行一个模式,配合-f参数使用:grep -f suspicious_patterns.txt /var/log/nginx/access.log这么做的好处是:积累的特征可以复用、可以沉淀。比如你发现某段时间有人在批量扫描某个漏洞路径,把路径特征加进清单里,下次遇到类似情况,直接跑一遍就能筛出来。运维的巡检脚本思路用到安全日志分析上,完全行得通。3. awk:把日志行拆开,数据才真正开始说话3.1 日志是一行一行的文本,但信息藏在字段里grep 帮你把可疑的行筛出来了,但行只是原材料。真正有价值的分析,发生在把一行日志拆成一个个字段之后。我当年在运维岗上对 awk 的印象就是“处理列的工具”,打印第一列、第三列数据。转安全后,我发现它的价值远不止于此。举个最典型的场景:分析 sshd 爆破攻击。日志里相关的那一行长这样:Mar 15 03:12:44 webserver sshd[25631]: Failed password for root from 203.0.113.45 port 54321 ssh2我想知道的是:有哪些 IP 在尝试爆破?每 IP 试了多少次?用 grep 能做但很费劲,用 awk 就是几秒钟的事:awk '/Failed password/ {print $(NF-3)}' /var/log/secure | sort | uniq -c | sort -rn解释一下这条命令干了什么:/Failed password/是模式匹配,只处理包含这个关键字的行;$(NF-3)表示当前行的倒数第 4 个字段。上面那行日志里,倒数第 4 个字段就是 IP 地址203.0.113.45。这就体现了 awk 的一个思维转变:它不关心字段的绝对位置,而可以用NF(字段总数)来从后往前取。因为 sshd 日志的 IP 位置相对固定,但前面日期、主机名的空格数可能不固定,从后面往前数反而更稳定。运行结果会是一串 IP 和计数,一眼就能看出哪几个 IP 在疯狂尝试,哪些只是零星几下。这个输出,就是后续封禁和溯源的基础。3.2 用 awk 做字段提取的细节,全看分隔符awk 默认按空白字符拆分字段,空格和 Tab 都算分隔符。但很多日志不是用空格分隔的,比如 access.log 的字段之间是空格没错,但请求行本身包含空格;再比如某些业务日志用逗号、竖线分隔。这时候要显式指定分隔符。看一个实际例子。nginx access.log 的默认格式大概是:203.0.113.45 - - [15/Mar/2025:03:12:44 +0800] "POST /login HTTP/1.1" 200 532 "-" "Mozilla/5.0"想提取“客户端 IP、请求方法、URL、状态码”,可以这样写:awk '{print $1, $6, $7, $9}' /var/log/nginx/access.log这里$6是请求行里的方法(POST),$7是路径(/login),$9是状态码。注意$6前面带一个双引号("POST),所以如果想拿到干净的字段,要稍微处理一下。这个细节在写分析命令时要心里有数。如果日志是 JSON 格式的,或者字段用逗号分隔,就指定-F:awk -F',' '{print $2, $5}' /var/log/app.log3.3 用 awk 直接做统计和累加awk 不仅能提取字段,还能在提取的同时做运算。这是它比纯文本工具更强的地方。假设我怀疑某个接口在被恶意刷,想统计每个来源 IP 对/api/order的请求次数。一条命令就能得到结果:awk '$7 == "/api/order" {count[$1]++} END {for (ip in count) print ip, count[ip]}' /var/log/nginx/access.logcount[$1]++的意思是拿第一列(IP)当数组下标,每出现一次就加 1。END块里遍历数组,把每个 IP 和它的计数打印出来。如果再配合sort -rn,排名就出来了。这种思路在安全分析里非常常用。比如统计每个来源 IP 触发了多少 WAF 拦截规则、统计每个用户的登录失败次数、统计某个时间窗口内异常状态码的分布。只要日志里能拆出维度字段,awk 就能按这个维度做聚合。3.4 给刚上手的人提个醒:awk 脚本别写复杂awk 能做的事情非常多,条件、循环、函数、格式化输出都能来。但我的建议是:日常安全分析里,awk 就干两件事——拆字段、做累加。超过这两件事,要么拆成多步命令,要么写独立的脚本。原因很简单:命令行里写复杂 awk 脚本,可读性太差。你自己写的命令,过两天回来看可能都想不起来逻辑是什么,更别说团队协作的时候别人怎么看得懂。我见过有人在命令行里写一长串 awk 处理逻辑,结果一个括号没配对,调试了半天。真正高效的排查流程是:先用简单命令快速确认方向,再慢慢完善细节。复杂逻辑放进脚本文件,加上注释才是正路。比如上面的统计需求,我会把 IP 列表先抽出来:awk '$7 == "/api/order" {print $1}' /var/log/nginx/access.log > ip_list.txt然后交给下面要讲的 sort 和 uniq 去处理。每个阶段只做一件事,清晰又不容易出错。4. sed:按时间和位置精准切日志4.1 分析大日志前,先切出时间窗口日志文件动辄几个 GB,直接在全文上跑分析不是不行,但效率很低。安全排查几乎总是围绕一个明确的时间窗口展开的:告警是 14:30 触发的,那就要看 14:20 到 14:40 之间发生了什么。这时候 sed 就派上用场了。sed 是流编辑器,它的经典用法是按地址范围处理文本。按时间窗口切日志,用的是地址范围配合打印操作:sed -n '/25\/Mar\/2025:14:20/,/25\/Mar\/2025:14:40/p' /var/log/nginx/access.log > window.log这条命令的意思是:从匹配25/Mar/2025:14:20的行开始,到匹配25/Mar/2025:14:40的行结束,把这个范围内的所有行打印出来,重定向到一个新文件。-n是关闭默认输出,只打印我们指定的内容。切出来之后,后续的 grep、awk 操作都在这个临时文件上跑,速度会快很多,也不会被窗口之外的历史数据干扰。4.2 sed 匹配时间窗口时最容易踩的坑我一开始用这个方法时,遇到过一种很隐蔽的问题:如果我指定的起止时间字符串不够精确,sed 可能会从错误的地方开始或者结束。举个例子,access.log 的行里时间格式是[15/Mar/2025:03:12:44 +0800]。如果我写:sed -n '/Mar 15 03/,/Mar 15 04/p' access.log注意这个模式可能会匹配到Mar 15 03,但它也会匹配Mar 15 03:59:59之后的所有行——因为只要行里包含Mar 15 03这个子串就行。如果哪个行里有别的字段恰好包含这个串,也会被误伤。解决方法是让匹配模式尽量完整。要么包含到分钟甚至秒,要么直接匹配时间戳的前半段带上方括号:sed -n '/\[15\/Mar\/2025:03:/,/\[15\/Mar\/2025:04:/p' access.log另一个实际问题:跨天的日志。从31/Mar/2025:23:30切到01/Apr/2025:00:30,如果日期不写全,sed 的匹配会直接失败或截取错误区间。所以跨天日志要带上完整日期再匹配。4.3 sed 的另一个安全用途:日志脱敏再外发除了切窗口,sed 还有一手绝活在安全场景里非常有用——脱敏。排查过程中经常要把日志片段发给同事、客户,或者贴到工单系统里,但日志里可能包含真实 IP、用户名、手机号之类的敏感信息。直接发原日志不妥,手工删又费劲,这种情况用 sed 做自动替换就很方便。比如把所有 IPv4 地址替换成[IP]:sed -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/[IP]/g' window.log > sanitized.log命令里-E启用扩展正则,替换的目标是把形如203.0.113.45的地址整体变成一个占位符。同理,可以把邮箱替换成[EMAIL]、把用户名替换成[USER],再外发就放心多了。这个操作看起来很不起眼,但在实际工作中很重要。安全分析本身就涉及敏感数据,能不能规范地处理日志脱敏,体现的是你的职业素养。我见过有人图省事直接发原始日志给外部人员,后来惹出麻烦的案例。用 sed 做一层替换,成本极低,但能避免很多后续风险。4.4 我个人的使用习惯总结我用 sed 的频度不如 grep 和 awk,但只要用到,基本就是两种情况:一是给整个排查流程划定边界,先把某段时间的数据准备好;二是做数据清洗、字段变形、脱敏。它更像是一个“预处理工具”,而不是直接出结论的工具。另外说一句:sed -i这种原地修改文件的用法,在安全分析时我非常不推荐直接对原始日志执行。日志是证据,一旦动了原始文件,后续走流程、出报告时很难说清楚。正确做法永远是先拷贝、再处理、保留原始文件不动。这和在运维时改配置前先备份是一个道理。5. sort 和 uniq:排序去重,把数据变成结论5.1 uniq 有个大前提:必须先排序前面几次示例里,我都写了sort | uniq -c“这样的组合,很多朋友可能没意识到,去重计数”必须先经过 sort。uniq这个命令的名字容易误导人,它其实只去掉“相邻且重复”的行,不是全局去重。换句话说,如果重复内容没有连续排列,uniq 是看不到的。举个具体的例子。假设某个文件里有:11.22.33.44 55.66.77.88 11.22.33.44直接执行uniq -c,它会认为三行都不重复,因为第二行的 IP 和第三行的 IP 之间隔着一行。只有先sort把相同的 IP 排到一起,再执行uniq -c,才能得到正确的统计结果:sort ip_list.txt | uniq -c我在带新人时见过很多次这种错误:花了大半天从日志里提取 IP,结果统计完发现同一个 IP 出现了好几行,等于前面白干了。这个细节,没在真实日志上踩过坑的人很容易忽略。5.2 sort 的排序要分清“字典序”和“数字序”sort 默认是按字典序(字符顺序)排序的,这对数字来说会出问题。比如10会排在2前面,因为按字符比较,1小于2。这看起来像是常识,但真到了统计访问量排名的时候,一旦忘了加-n,你看到的 TOP 列表会完全不对。正确姿势是:sort -rn ip_count.txt这里的-n表示按数字大小排序,-r表示逆序,从大到小。安全分析里,这可能是最常用的一条排序命令:把 awk 统计出来的计数从高到低排列,谁最可疑一目了然。如果要对日志里的某个字段排序,但字段之间用分隔符(比如逗号、竖线)隔开,要指定列:sort -t',' -k2 -rn data.csv-t','指定分隔符是逗号,-k2指定按第二列排序,-rn按数字逆序。这在处理导出的业务日志时特别有用。5.3 组合拳:一条命令找出 TOP 攻击源现在把所有东西连起来看一个完整的分析任务。某客户反馈有人在刷他们的登录接口,现象是短时间内大量POST /api/v1/login请求,并且伴随大量失败返回。我先从日志里筛出所有登录接口的请求行:grep "POST /api/v1/login" /var/log/nginx/access.log > login.log然后提取客户端 IP 并统计每个 IP 的请求次数:awk '{print $1}' login.log | sort | uniq -c | sort -rn | head -20执行完就能得到一张 20 行的表:每行包含一个数字和一个 IP,数字代表请求次数。如果前几个 IP 的请求次数是断崖式的,比如第一、第二是几千次,其余都只有个位数,基本可以锁定问题 IP。后续无论是封禁、溯源、还是写报告,这个输出就是核心依据。再补充一个技巧:用uniq -d只显示重复的行,比如从用户登录日志里找同一个 IP 在短时间内多次切换账号的可疑行为。uniq -d配合其他命令,在做撞库、批量注册这类分析时非常有用。5.4 把 sort 和 uniq 当“验证工具”而不是“统计工具”很多人把 sort 和 uniq 只当统计工具用,我其实更愿意把它们当作验证工具。比如你怀疑某个时间段内有扫描行为,你不需要精确统计到底扫了多少次,你只需要确认“异常增多”这个事实。用sort | uniq -c把结果列出来,观察数据分布的形状,比盯着具体数值更有价值。正常流量下,每个 IP 的请求次数分布相对平缓。攻击流量下,头部几个 IP 的计数会明显异常高。这种“一眼看出不对劲”的能力,就是靠 sort 和 uniq 把你从海量日志中拉出来的。6. 实战记录:一次完整的安全排查是怎么用这 5 个命令串起来的6.1 告警触发和初步确认某天下午,我接到某客户反馈:他们对外提供的一个查询接口响应时间从平均 200 毫秒飙升到 5 秒以上,并且持续了将近半小时。客户很紧张,怀疑是被拖库了。我先登上了他们的 nginx 服务器,确认了 access.log 的位置和时间跨度。第一步从日志里抓升高响应时间段的数据,用 sed 切出指定时间窗口,大概是从 14:10 到 14:40,一共 30 分钟。这是一个合理的排查范围:告警触发在 14:30,往前推 20 分钟是异常开始的时间。sed -n '/28\/Mar\/2025:14:10/,/28\/Mar\/2025:14:40/p' /var/log/nginx/access.log > window.log6.2 先用 grep 做特征筛查,锁定可疑路径切出窗口之后,我没有急着看全量数据,而是先用 grep 做特征筛查。客户业务是查询类接口,正常情况请求应该集中在少数几个固定路径上。我先把请求方法为 POST、状态码异常的行过滤出来看个大概:grep -E "POST.*(sql|select|union|login|api/)" window.log | head -50筛出来的结果里立刻出现了几条请求路径和参数里带union select的请求——SQL 注入特征非常明显。但当时我并没有直接下结论,因为 head -50 只能看到前 50 行,特征出现只要几行,不能说明这就是导致响应变慢的原因。这里插一句我的经验:攻击特征命中不一定是攻击本身,也可能是扫描器在试探。你要看的是“量级”和“频率”。所以我接下来做的不是翻更多行,而是统计这些可疑特征在窗口内一共出现了多少次:grep -c -E "union select|information_schema|sleep\(" window.log数量是 300 多,对于一个正常业务来说,这个数字完全异常。6.3 用 awk 提取字段,聚合出可疑 IP 的分布确认“确实有异常流量”之后,接下来的问题就是“谁在发这些请求”。这一步用 awk 提取来源 IP:awk '/union select|information_schema/ {print $1}' window.log | sort | uniq -c | sort -rn | head -10输出结果里,排第一的 IP 占总可疑请求数的九成以上,其余 IP 只有零星几条。这就把“异常流量”缩小到了“单一来源 IP”。这一步做完,含义就完全不一样了:如果是分散的、来自各地的大量请求,可能是社会上的扫描团伙例行扫描,国内国外到处都有;但集中在一个 IP 上,基本可以确认是有人在有针对性地打这个接口。6.4 用 sed 提取攻击 IP 的完整请求记录,复原攻击路径锁定 IP 之后,我需要把它在这个时间窗口内发的所有请求都理出来,看看它到底做了什么。用 grep 再按 IP 筛一遍,还是用 sed?其实都可以,但我更推荐直接 grep 加上下文参数:grep -E "^203\.0\.113\.45" window.log > attacker.log为什么这里用 grep 而不是 sed?因为这个时候我们不再需要“按时间范围”,而是“按 IP 过滤”。把每条请求按时间排好之后,我用 sed 做了一步清洗,把请求行里的时间戳和状态码格式化得更易读,方便后续贴到报告里。sed -E 's/\[([^]]+)\].*"([A-Z]+) ([^"]+)".*"([0-9]+)"/\1 \2 \3 \4/' attacker.log这一步纯粹是格式整理,让日志从原始的一长串变成更容易阅读的表格。虽然不影响分析结论,但对出报告很有帮助。6.5 最终结论和排查报告把整个流程跑完,最后得到的结论非常清晰:一个固定 IP 在 30 分钟内发送了三百多条带有 SQL 注入特征的请求,请求集中在查询接口,并伴随大量响应超时。结合接口日志中出现了sleep函数特征,可以判断攻击者可能在尝试基于时间盲注。整个过程用时不超过二十分钟,没有用到任何商业安全产品,就靠这几个命令反复组合。我把这条排查链路总结成了一个小脚本,放到自己的工具箱里。下次再遇到类似的接口异常,先跑通用分析脚本,再按输出结果深入,效率提高了很多。7. 常见问题与排查技巧实录7.1 我见过的五个高频错误和对应解法趁这个机会,我把日志分析里最常见的问题整理成一张表,都是实际操作中踩过的坑,希望能帮你少走弯路。常见问题现象原因解决方式uniq 统计结果不准确同一 IP 分多行展示未先 sort 就去重总是写成sort | uniq -c的组合sort 数字排序不对“10”排在“9”前面默认字典序,非数字序加-n参数按数字排序grep 匹配 IP 误报多匹配到包含该串的其他地址子串匹配无边界用 `(^sed 切窗口区间错误日志截取范围不对匹配锚点不够精确日期和时间带完整再匹配直接在原日志上修改原始证据被破坏直接对原文件操作先cp或重定向到新文件再处理这张表里的每一条,我都在真实环境里踩过。有些是刚转安全时犯的错,有些是后来带新人时看他们反复犯的错。把它们记下来,能省很多时间。7.2 几个提升效率的实战心得除了上面的坑,我还有几个已经内化为习惯的做法。第一,分析前先看文件大小和时间范围。拿到一个日志文件,先ls -lh看大小,再head -3看格式,再tail -3看最新记录。一看格式就知道字段结构,一看大小就知道要不要先切窗口。别上来就直接跑分析命令。第二,把常用分析链路沉淀成脚本。比如我把“从 access.log 里找出 TOP 10 来源 IP”这套命令写成了一个函数,存到自己的环境配置里,每次登录服务器都能直接调用,输入日志路径就出结果。这不是什么高深的自动化,就是把自己反复做的事情固化下来。第三,命令跑完先存输出,再人脑分析。很多新人的习惯是看命令行输出的前几行就急着下结论。我现在的习惯是:不管结果看起来多明显,先把输出重定向到文件,再打开文件完整看一遍。因为终端里滚屏会丢掉大量内容,很可能前面 20 行正常、后面几百行才是一眼假的东西。用文件保存输出,既保留了证据,也不容易漏信息。7.3 从运维思维到安全思维,差的不是技术最后说一点我在职业转型上最深的体会。运维看日志,目标是确认系统处于什么状态;安全看日志,目标是确认系统是否被攻击、被谁攻击、攻击到什么程度。同样的命令,不同的提问方式。有 Linux 基础的人转安全,真的是站在一个相对高的起点上。至少你不用从“文件怎么浏览、权限怎么管理”开始学,你缺的不是技术栈,而是把技术栈迁移到新场景的意识。学会用日志讲一个“攻击故事”,你就已经入门了。还有一个对我帮助很大、建议你也试试的习惯:每次做完一次排查,花十分钟把用过的命令整理成一条流水线,注释好每一段是干什么的。存着不吃亏。我自己的这套组合命令脚本,就是从最开始的一条条零散命令,慢慢沉淀成了一套比较完整的排查模板。等到你手头有了一套自己的模板,再遇到突发情况,就能从容很多。
凌晨三点,手机震动。我摸黑爬起来,屏幕上显示“生产环境访问异常”的告警。那种心跳加速的感觉,做过运维的都懂。但这次,我已经从运维岗转到了安全方向,手里的工具没变,变的只是看问题的角度。日志就在那,几百万行躺着,静悄悄地记录了一切。关键是你知不知道看哪里、怎么看。很多人一听“安全分析”就觉得是高大上的 SIEM 平台、复杂的攻击链还原,其实真到了应急响应那一刻,先用顺手的反而是最朴素的几个 Linux 命令。我转安全这几年,最深的体会是:那些年在运维岗上天天用的基本功,一样都没有浪费。这篇文章我就聊聊自己从运维转安全后,用的最多的 5 个日志分析命令 — grep、awk、sed、sort、uniq,以及它们到底怎么在安全排查里组合起来干活。适合正在考虑转安全的运维朋友、刚入门的安全新人,也适合那些觉得日志分析很玄乎、想从实操入手的同学。看完你会发现,转型的第一步不是学新东西,而是把已经会的东西换个思路用。1. 为什么日志分析是运维转安全的第一站1.1 日志在运维眼里是告警,在安全眼里是案发现场做运维的时候,我看日志是为了回答三个问题:系统为什么慢了?服务为什么挂了?磁盘为什么满了?那时候日志是排障工具,只要把错误信息捞出来、定位到具体模块,任务就算完成。转了安全之后,同样一份日志,要回答的问题完全变了——谁进来了?怎么进来的?进来之后干了什么?已经走了还是还在?同样是看/var/log/secure,运维关心的是“哪个用户登录失败了”,安全关心的是“同一个 IP 在五分钟内试了一百次密码,是不是在爆破”。这种视角的转换,不需要把 Linux 推倒重学。恰恰相反,用的还是那套管道符、重定向、正则表达式。日志分析本质上是文本处理,安全日志和业务日志在格式上没有本质区别,区别只在于你要从里面提取什么信号。1.2 为什么先学组合命令,而不是直接上安全分析平台有些朋友上来就研究各种复杂的日志分析平台、可视化大屏,我觉得顺序反了。平台是辅助,底层能力才是核心。原因有几个:第一,应急响应往往发生在客户现场或者老旧的跳板机上,环境简陋到什么程度都不奇怪,可能连包管理器都不让你装。这时候你总不能说“等我搭个平台再排查吧”。手里有 Bash,就什么都不慌。第二,安全分析平台展示的告警、趋势图,底层逻辑依然是筛选、聚合、排序、统计。搞懂 grep 怎么做条件过滤、awk 怎么做字段提取、sort 和 uniq 怎么做排序去重,再用任何平台都能一眼看穿它背后的查询逻辑,不会被参数和图表带偏。第三,日志分析不是一次性的动作,而是一个反复迭代的过程。你可能要先快速筛一遍看有没有明显特征,再深入提取数据,再换个维度重新看。这种快速试错的节奏,靠命令行管道是最舒服的,改一个参数、加一个条件,立刻就能跑出新结果。1.3 五个命令的分工与协作关系我给自己总结过一个非常朴素的日志分析流水线:先缩小范围,再拆解字段,然后排序、去重、计数,最后得出结论。五个命令正好对应这条流水线的五个环节。grep 负责条件过滤,像一道筛子,把几百万行日志里符合条件的行捞出来。awk 负责字段拆解和统计,把日志行按空格或逗号切开,提取 IP、状态码、耗时这些关键信息,还能直接做累加计数。sed 负责区间截取和文本变形,在大量日志里切出特定时间窗口的内容,或者做敏感信息脱敏。sort 负责排序,让数据从杂乱无章变成有规律可循。uniq 负责去重和计数,配合 sort 使用,能快速找出“哪个 IP 最活跃”、“哪种攻击特征出现最多”。单个命令都很简单,难的是把它们串起来。管道符加起来的战斗力,远超任何一个命令单独使用的效果。下面我按自己在真实排查里用得最多的场景,把这五个命令逐一拆开讲清楚。2. grep:安全日志的第一道筛子2.1 从一次网站被刷说起去年帮某客户排查一次网站访问异常。客户的反馈是首页响应很慢,打开要十几秒。按运维思维先查负载、查连接数,指标看着都还算正常,但业务就是卡。后来我去翻了 nginx 的 access.log,先用 grep 做了个很简单的过滤:grep -c "HTTP/1.1\" 502" /var/log/nginx/access.log执行完我就有点数了:过去一小时里 502 出现了两千多次,正常情况下这个数字应该是几十。网站的故障表象是慢,但真正的异常逻辑藏在日志的这列状态码里。这就是我要说的第一件事:grep 是最基础的筛选工具,但它在安全分析里的用法,和运维排障时不完全一样。运维通常用 grep 找某个明确的错误关键字,比如grep "OutOfMemory"。而安全分析时,你要筛的往往不是“确定发生了什么”,而是“有没有我没见过的异常迹象”,所以反过来,我更多用 grep 去“排除”噪音,把正常的请求过滤掉,剩下的就是可疑的东西。2.2 安全场景里真正有用的几个 grep 用法基础语法我就不啰嗦了,grep [选项] 模式 文件。我重点说几个实战里高频用到的选项。第一个是-E,扩展正则。在 access.log 里分析可疑扫描行为时,经常要同时匹配多个特征。比如想筛出所有访问路径里带admin、manager、phpmyadmin的请求,一句话就搞定:grep -E "/admin|/manager|/phpmyadmin" /var/log/nginx/access.log | head -100第二个是-v,反向匹配。健康检查、监控探针这类请求会污染分析结果,每次都得先踢掉它们:grep -v -E "User-Agent: (ELB-HealthChecker|kube-probe)" /var/log/nginx/access.log第三个是-c,统计数量。不要一上来就全量看内容,先计数,数量异常本身就是信号。比如想看某台机器上 sshd 登录失败的次数,直接:grep -c "Failed password" /var/log/secure2.3 一个必须养成的习惯:IP 匹配一定要加边界这个坑我踩过好几次。比如你想筛来自某个 IP 的请求,直接写grep "192.168.1.100",可能会把192.168.1.1000、192.168.1.1001这种根本不存在的地址也带进来,更麻烦的是会把192.168.1.100.5这类畸形请求混进来。因为 grep 是子串匹配,它不管字符前后是什么。正确姿势是给 IP 加上边界,保证匹配到的是完整的地址:grep -E "(^|[^0-9.])192\.168\.1\.100([^0-9.]|$)" /var/log/nginx/access.log看着麻烦,但这条命令的价值在于:当你把可疑 IP 的特征写到告警规则、写到自动化脚本里时,不会因为草率匹配产生大量误报。运维阶段的教训是“日志里有噪音分析不出结果”,安全阶段的教训是“误报太多,真正告警就没人在意了”。2.4 我的实操建议:把 grep 特征写成清单用 grep 做安全分析,最大的忌讳是每次都在命令行里临时编正则,想到一个写一个,结果反复敲一长串。我会把常用的筛选用法沉淀成一个小脚本,或者直接写成 grep 特征清单文件,一行一个模式,配合-f参数使用:grep -f suspicious_patterns.txt /var/log/nginx/access.log这么做的好处是:积累的特征可以复用、可以沉淀。比如你发现某段时间有人在批量扫描某个漏洞路径,把路径特征加进清单里,下次遇到类似情况,直接跑一遍就能筛出来。运维的巡检脚本思路用到安全日志分析上,完全行得通。3. awk:把日志行拆开,数据才真正开始说话3.1 日志是一行一行的文本,但信息藏在字段里grep 帮你把可疑的行筛出来了,但行只是原材料。真正有价值的分析,发生在把一行日志拆成一个个字段之后。我当年在运维岗上对 awk 的印象就是“处理列的工具”,打印第一列、第三列数据。转安全后,我发现它的价值远不止于此。举个最典型的场景:分析 sshd 爆破攻击。日志里相关的那一行长这样:Mar 15 03:12:44 webserver sshd[25631]: Failed password for root from 203.0.113.45 port 54321 ssh2我想知道的是:有哪些 IP 在尝试爆破?每 IP 试了多少次?用 grep 能做但很费劲,用 awk 就是几秒钟的事:awk '/Failed password/ {print $(NF-3)}' /var/log/secure | sort | uniq -c | sort -rn解释一下这条命令干了什么:/Failed password/是模式匹配,只处理包含这个关键字的行;$(NF-3)表示当前行的倒数第 4 个字段。上面那行日志里,倒数第 4 个字段就是 IP 地址203.0.113.45。这就体现了 awk 的一个思维转变:它不关心字段的绝对位置,而可以用NF(字段总数)来从后往前取。因为 sshd 日志的 IP 位置相对固定,但前面日期、主机名的空格数可能不固定,从后面往前数反而更稳定。运行结果会是一串 IP 和计数,一眼就能看出哪几个 IP 在疯狂尝试,哪些只是零星几下。这个输出,就是后续封禁和溯源的基础。3.2 用 awk 做字段提取的细节,全看分隔符awk 默认按空白字符拆分字段,空格和 Tab 都算分隔符。但很多日志不是用空格分隔的,比如 access.log 的字段之间是空格没错,但请求行本身包含空格;再比如某些业务日志用逗号、竖线分隔。这时候要显式指定分隔符。看一个实际例子。nginx access.log 的默认格式大概是:203.0.113.45 - - [15/Mar/2025:03:12:44 +0800] "POST /login HTTP/1.1" 200 532 "-" "Mozilla/5.0"想提取“客户端 IP、请求方法、URL、状态码”,可以这样写:awk '{print $1, $6, $7, $9}' /var/log/nginx/access.log这里$6是请求行里的方法(POST),$7是路径(/login),$9是状态码。注意$6前面带一个双引号("POST),所以如果想拿到干净的字段,要稍微处理一下。这个细节在写分析命令时要心里有数。如果日志是 JSON 格式的,或者字段用逗号分隔,就指定-F:awk -F',' '{print $2, $5}' /var/log/app.log3.3 用 awk 直接做统计和累加awk 不仅能提取字段,还能在提取的同时做运算。这是它比纯文本工具更强的地方。假设我怀疑某个接口在被恶意刷,想统计每个来源 IP 对/api/order的请求次数。一条命令就能得到结果:awk '$7 == "/api/order" {count[$1]++} END {for (ip in count) print ip, count[ip]}' /var/log/nginx/access.logcount[$1]++的意思是拿第一列(IP)当数组下标,每出现一次就加 1。END块里遍历数组,把每个 IP 和它的计数打印出来。如果再配合sort -rn,排名就出来了。这种思路在安全分析里非常常用。比如统计每个来源 IP 触发了多少 WAF 拦截规则、统计每个用户的登录失败次数、统计某个时间窗口内异常状态码的分布。只要日志里能拆出维度字段,awk 就能按这个维度做聚合。3.4 给刚上手的人提个醒:awk 脚本别写复杂awk 能做的事情非常多,条件、循环、函数、格式化输出都能来。但我的建议是:日常安全分析里,awk 就干两件事——拆字段、做累加。超过这两件事,要么拆成多步命令,要么写独立的脚本。原因很简单:命令行里写复杂 awk 脚本,可读性太差。你自己写的命令,过两天回来看可能都想不起来逻辑是什么,更别说团队协作的时候别人怎么看得懂。我见过有人在命令行里写一长串 awk 处理逻辑,结果一个括号没配对,调试了半天。真正高效的排查流程是:先用简单命令快速确认方向,再慢慢完善细节。复杂逻辑放进脚本文件,加上注释才是正路。比如上面的统计需求,我会把 IP 列表先抽出来:awk '$7 == "/api/order" {print $1}' /var/log/nginx/access.log > ip_list.txt然后交给下面要讲的 sort 和 uniq 去处理。每个阶段只做一件事,清晰又不容易出错。4. sed:按时间和位置精准切日志4.1 分析大日志前,先切出时间窗口日志文件动辄几个 GB,直接在全文上跑分析不是不行,但效率很低。安全排查几乎总是围绕一个明确的时间窗口展开的:告警是 14:30 触发的,那就要看 14:20 到 14:40 之间发生了什么。这时候 sed 就派上用场了。sed 是流编辑器,它的经典用法是按地址范围处理文本。按时间窗口切日志,用的是地址范围配合打印操作:sed -n '/25\/Mar\/2025:14:20/,/25\/Mar\/2025:14:40/p' /var/log/nginx/access.log > window.log这条命令的意思是:从匹配25/Mar/2025:14:20的行开始,到匹配25/Mar/2025:14:40的行结束,把这个范围内的所有行打印出来,重定向到一个新文件。-n是关闭默认输出,只打印我们指定的内容。切出来之后,后续的 grep、awk 操作都在这个临时文件上跑,速度会快很多,也不会被窗口之外的历史数据干扰。4.2 sed 匹配时间窗口时最容易踩的坑我一开始用这个方法时,遇到过一种很隐蔽的问题:如果我指定的起止时间字符串不够精确,sed 可能会从错误的地方开始或者结束。举个例子,access.log 的行里时间格式是[15/Mar/2025:03:12:44 +0800]。如果我写:sed -n '/Mar 15 03/,/Mar 15 04/p' access.log注意这个模式可能会匹配到Mar 15 03,但它也会匹配Mar 15 03:59:59之后的所有行——因为只要行里包含Mar 15 03这个子串就行。如果哪个行里有别的字段恰好包含这个串,也会被误伤。解决方法是让匹配模式尽量完整。要么包含到分钟甚至秒,要么直接匹配时间戳的前半段带上方括号:sed -n '/\[15\/Mar\/2025:03:/,/\[15\/Mar\/2025:04:/p' access.log另一个实际问题:跨天的日志。从31/Mar/2025:23:30切到01/Apr/2025:00:30,如果日期不写全,sed 的匹配会直接失败或截取错误区间。所以跨天日志要带上完整日期再匹配。4.3 sed 的另一个安全用途:日志脱敏再外发除了切窗口,sed 还有一手绝活在安全场景里非常有用——脱敏。排查过程中经常要把日志片段发给同事、客户,或者贴到工单系统里,但日志里可能包含真实 IP、用户名、手机号之类的敏感信息。直接发原日志不妥,手工删又费劲,这种情况用 sed 做自动替换就很方便。比如把所有 IPv4 地址替换成[IP]:sed -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/[IP]/g' window.log > sanitized.log命令里-E启用扩展正则,替换的目标是把形如203.0.113.45的地址整体变成一个占位符。同理,可以把邮箱替换成[EMAIL]、把用户名替换成[USER],再外发就放心多了。这个操作看起来很不起眼,但在实际工作中很重要。安全分析本身就涉及敏感数据,能不能规范地处理日志脱敏,体现的是你的职业素养。我见过有人图省事直接发原始日志给外部人员,后来惹出麻烦的案例。用 sed 做一层替换,成本极低,但能避免很多后续风险。4.4 我个人的使用习惯总结我用 sed 的频度不如 grep 和 awk,但只要用到,基本就是两种情况:一是给整个排查流程划定边界,先把某段时间的数据准备好;二是做数据清洗、字段变形、脱敏。它更像是一个“预处理工具”,而不是直接出结论的工具。另外说一句:sed -i这种原地修改文件的用法,在安全分析时我非常不推荐直接对原始日志执行。日志是证据,一旦动了原始文件,后续走流程、出报告时很难说清楚。正确做法永远是先拷贝、再处理、保留原始文件不动。这和在运维时改配置前先备份是一个道理。5. sort 和 uniq:排序去重,把数据变成结论5.1 uniq 有个大前提:必须先排序前面几次示例里,我都写了sort | uniq -c“这样的组合,很多朋友可能没意识到,去重计数”必须先经过 sort。uniq这个命令的名字容易误导人,它其实只去掉“相邻且重复”的行,不是全局去重。换句话说,如果重复内容没有连续排列,uniq 是看不到的。举个具体的例子。假设某个文件里有:11.22.33.44 55.66.77.88 11.22.33.44直接执行uniq -c,它会认为三行都不重复,因为第二行的 IP 和第三行的 IP 之间隔着一行。只有先sort把相同的 IP 排到一起,再执行uniq -c,才能得到正确的统计结果:sort ip_list.txt | uniq -c我在带新人时见过很多次这种错误:花了大半天从日志里提取 IP,结果统计完发现同一个 IP 出现了好几行,等于前面白干了。这个细节,没在真实日志上踩过坑的人很容易忽略。5.2 sort 的排序要分清“字典序”和“数字序”sort 默认是按字典序(字符顺序)排序的,这对数字来说会出问题。比如10会排在2前面,因为按字符比较,1小于2。这看起来像是常识,但真到了统计访问量排名的时候,一旦忘了加-n,你看到的 TOP 列表会完全不对。正确姿势是:sort -rn ip_count.txt这里的-n表示按数字大小排序,-r表示逆序,从大到小。安全分析里,这可能是最常用的一条排序命令:把 awk 统计出来的计数从高到低排列,谁最可疑一目了然。如果要对日志里的某个字段排序,但字段之间用分隔符(比如逗号、竖线)隔开,要指定列:sort -t',' -k2 -rn data.csv-t','指定分隔符是逗号,-k2指定按第二列排序,-rn按数字逆序。这在处理导出的业务日志时特别有用。5.3 组合拳:一条命令找出 TOP 攻击源现在把所有东西连起来看一个完整的分析任务。某客户反馈有人在刷他们的登录接口,现象是短时间内大量POST /api/v1/login请求,并且伴随大量失败返回。我先从日志里筛出所有登录接口的请求行:grep "POST /api/v1/login" /var/log/nginx/access.log > login.log然后提取客户端 IP 并统计每个 IP 的请求次数:awk '{print $1}' login.log | sort | uniq -c | sort -rn | head -20执行完就能得到一张 20 行的表:每行包含一个数字和一个 IP,数字代表请求次数。如果前几个 IP 的请求次数是断崖式的,比如第一、第二是几千次,其余都只有个位数,基本可以锁定问题 IP。后续无论是封禁、溯源、还是写报告,这个输出就是核心依据。再补充一个技巧:用uniq -d只显示重复的行,比如从用户登录日志里找同一个 IP 在短时间内多次切换账号的可疑行为。uniq -d配合其他命令,在做撞库、批量注册这类分析时非常有用。5.4 把 sort 和 uniq 当“验证工具”而不是“统计工具”很多人把 sort 和 uniq 只当统计工具用,我其实更愿意把它们当作验证工具。比如你怀疑某个时间段内有扫描行为,你不需要精确统计到底扫了多少次,你只需要确认“异常增多”这个事实。用sort | uniq -c把结果列出来,观察数据分布的形状,比盯着具体数值更有价值。正常流量下,每个 IP 的请求次数分布相对平缓。攻击流量下,头部几个 IP 的计数会明显异常高。这种“一眼看出不对劲”的能力,就是靠 sort 和 uniq 把你从海量日志中拉出来的。6. 实战记录:一次完整的安全排查是怎么用这 5 个命令串起来的6.1 告警触发和初步确认某天下午,我接到某客户反馈:他们对外提供的一个查询接口响应时间从平均 200 毫秒飙升到 5 秒以上,并且持续了将近半小时。客户很紧张,怀疑是被拖库了。我先登上了他们的 nginx 服务器,确认了 access.log 的位置和时间跨度。第一步从日志里抓升高响应时间段的数据,用 sed 切出指定时间窗口,大概是从 14:10 到 14:40,一共 30 分钟。这是一个合理的排查范围:告警触发在 14:30,往前推 20 分钟是异常开始的时间。sed -n '/28\/Mar\/2025:14:10/,/28\/Mar\/2025:14:40/p' /var/log/nginx/access.log > window.log6.2 先用 grep 做特征筛查,锁定可疑路径切出窗口之后,我没有急着看全量数据,而是先用 grep 做特征筛查。客户业务是查询类接口,正常情况请求应该集中在少数几个固定路径上。我先把请求方法为 POST、状态码异常的行过滤出来看个大概:grep -E "POST.*(sql|select|union|login|api/)" window.log | head -50筛出来的结果里立刻出现了几条请求路径和参数里带union select的请求——SQL 注入特征非常明显。但当时我并没有直接下结论,因为 head -50 只能看到前 50 行,特征出现只要几行,不能说明这就是导致响应变慢的原因。这里插一句我的经验:攻击特征命中不一定是攻击本身,也可能是扫描器在试探。你要看的是“量级”和“频率”。所以我接下来做的不是翻更多行,而是统计这些可疑特征在窗口内一共出现了多少次:grep -c -E "union select|information_schema|sleep\(" window.log数量是 300 多,对于一个正常业务来说,这个数字完全异常。6.3 用 awk 提取字段,聚合出可疑 IP 的分布确认“确实有异常流量”之后,接下来的问题就是“谁在发这些请求”。这一步用 awk 提取来源 IP:awk '/union select|information_schema/ {print $1}' window.log | sort | uniq -c | sort -rn | head -10输出结果里,排第一的 IP 占总可疑请求数的九成以上,其余 IP 只有零星几条。这就把“异常流量”缩小到了“单一来源 IP”。这一步做完,含义就完全不一样了:如果是分散的、来自各地的大量请求,可能是社会上的扫描团伙例行扫描,国内国外到处都有;但集中在一个 IP 上,基本可以确认是有人在有针对性地打这个接口。6.4 用 sed 提取攻击 IP 的完整请求记录,复原攻击路径锁定 IP 之后,我需要把它在这个时间窗口内发的所有请求都理出来,看看它到底做了什么。用 grep 再按 IP 筛一遍,还是用 sed?其实都可以,但我更推荐直接 grep 加上下文参数:grep -E "^203\.0\.113\.45" window.log > attacker.log为什么这里用 grep 而不是 sed?因为这个时候我们不再需要“按时间范围”,而是“按 IP 过滤”。把每条请求按时间排好之后,我用 sed 做了一步清洗,把请求行里的时间戳和状态码格式化得更易读,方便后续贴到报告里。sed -E 's/\[([^]]+)\].*"([A-Z]+) ([^"]+)".*"([0-9]+)"/\1 \2 \3 \4/' attacker.log这一步纯粹是格式整理,让日志从原始的一长串变成更容易阅读的表格。虽然不影响分析结论,但对出报告很有帮助。6.5 最终结论和排查报告把整个流程跑完,最后得到的结论非常清晰:一个固定 IP 在 30 分钟内发送了三百多条带有 SQL 注入特征的请求,请求集中在查询接口,并伴随大量响应超时。结合接口日志中出现了sleep函数特征,可以判断攻击者可能在尝试基于时间盲注。整个过程用时不超过二十分钟,没有用到任何商业安全产品,就靠这几个命令反复组合。我把这条排查链路总结成了一个小脚本,放到自己的工具箱里。下次再遇到类似的接口异常,先跑通用分析脚本,再按输出结果深入,效率提高了很多。7. 常见问题与排查技巧实录7.1 我见过的五个高频错误和对应解法趁这个机会,我把日志分析里最常见的问题整理成一张表,都是实际操作中踩过的坑,希望能帮你少走弯路。常见问题现象原因解决方式uniq 统计结果不准确同一 IP 分多行展示未先 sort 就去重总是写成sort | uniq -c的组合sort 数字排序不对“10”排在“9”前面默认字典序,非数字序加-n参数按数字排序grep 匹配 IP 误报多匹配到包含该串的其他地址子串匹配无边界用 `(^sed 切窗口区间错误日志截取范围不对匹配锚点不够精确日期和时间带完整再匹配直接在原日志上修改原始证据被破坏直接对原文件操作先cp或重定向到新文件再处理这张表里的每一条,我都在真实环境里踩过。有些是刚转安全时犯的错,有些是后来带新人时看他们反复犯的错。把它们记下来,能省很多时间。7.2 几个提升效率的实战心得除了上面的坑,我还有几个已经内化为习惯的做法。第一,分析前先看文件大小和时间范围。拿到一个日志文件,先ls -lh看大小,再head -3看格式,再tail -3看最新记录。一看格式就知道字段结构,一看大小就知道要不要先切窗口。别上来就直接跑分析命令。第二,把常用分析链路沉淀成脚本。比如我把“从 access.log 里找出 TOP 10 来源 IP”这套命令写成了一个函数,存到自己的环境配置里,每次登录服务器都能直接调用,输入日志路径就出结果。这不是什么高深的自动化,就是把自己反复做的事情固化下来。第三,命令跑完先存输出,再人脑分析。很多新人的习惯是看命令行输出的前几行就急着下结论。我现在的习惯是:不管结果看起来多明显,先把输出重定向到文件,再打开文件完整看一遍。因为终端里滚屏会丢掉大量内容,很可能前面 20 行正常、后面几百行才是一眼假的东西。用文件保存输出,既保留了证据,也不容易漏信息。7.3 从运维思维到安全思维,差的不是技术最后说一点我在职业转型上最深的体会。运维看日志,目标是确认系统处于什么状态;安全看日志,目标是确认系统是否被攻击、被谁攻击、攻击到什么程度。同样的命令,不同的提问方式。有 Linux 基础的人转安全,真的是站在一个相对高的起点上。至少你不用从“文件怎么浏览、权限怎么管理”开始学,你缺的不是技术栈,而是把技术栈迁移到新场景的意识。学会用日志讲一个“攻击故事”,你就已经入门了。还有一个对我帮助很大、建议你也试试的习惯:每次做完一次排查,花十分钟把用过的命令整理成一条流水线,注释好每一段是干什么的。存着不吃亏。我自己的这套组合命令脚本,就是从最开始的一条条零散命令,慢慢沉淀成了一套比较完整的排查模板。等到你手头有了一套自己的模板,再遇到突发情况,就能从容很多。