磨刀不误砍柴工:懂点Linux命令,你的工作效率会直接翻倍
做技术这一行,尤其是跟服务器、运维、后端打交道久了,你会发现一个很扎心的现实:很多人不是不会写代码,而是被命令行卡住了脖子。明明一个grep加awk就能从几G的日志里揪出报错信息,有人却要下载到本地用编辑器翻半天;明明一条rsync就能增量同步几十G的数据,有人还在用FileZilla拖拽到超时。Linux命令这东西,平时觉得不就是些字母组合嘛,真到关键时刻,它就是你和服务器之间唯一的沟通语言。我这篇不讲那种"命令大全"式的罗列,那种东西man手册里全都有。我想聊的是真正干活时那些高频命令的用法逻辑、组合思路,以及我在实际排障中踩过的坑和沉淀下来的套路。不管你是刚接触Linux的运维新人,还是写了几年业务代码想补补基本功的后端,看完这篇,你至少能把以前那些"复制粘贴然后祈祷有效"的操作,变成"我知道它在干嘛以及为什么这么干"。
1. 先聊聊我的看法:命令背不完,但思路可以学
我刚开始接触Linux那会儿,也干过拿个小本本抄命令的傻事,什么tar -zcvf、chmod 777,抄了满满一本。后来发现屁用没有,因为命令是死的,场景是活的。你背会了find / -name "*.log",但遇到"找出最近三天修改过且大于100M的日志文件"这种需求,照样懵。
为什么?因为缺的不是命令,是组合命令的思路。Linux的设计哲学特别有意思——它把每一个小工具都做到极致简单,然后通过管道|、重定向>、通配符*这些东西把工具串起来,像乐高积木一样搭出无穷无尽的功能。你写代码讲究函数拆分、模块复用,用命令其实也是一样的道理:单个命令是原子操作,管道和参数才是真正的业务逻辑。
另外一个很重要的思路是:优先掌握"排查链路"而不是"单个命令"。就好比你觉得服务器CPU飙高,光是敲个top看到某个进程占300%没有用,你得顺着这条线索往下摸——是哪个线程?在执行什么调用?是不是GC线程疯狂回收?这需要top、pidstat、jstack(Java场景)甚至perf一路查下去。所以我下面每一部分都会尽量以"真实场景"为入口,把一组命令串成一条完整的链路来讲。
2. 文件与目录:日常高频操作背后的完整逻辑
2.1 批量重命名几百个文件?用循环加变量,别手动改
有一次我需要在测试环境把一批带日期后缀的配置文件统一加上环境标识,比如把app_20240101.conf改成app_20240101_dev.conf,有三百多个文件。手动改?手能废掉。用文件管理器?处理不了那么多。这时候命令行的优势就出来了。
我的做法是先进到目录,看一眼规律:
ls -l *.conf | head -20确认所有文件名符合app_日期.conf这个格式后,直接一个for循环搞定:
for f in app_*.conf; do mv "$f" "${f%.conf}_dev.conf"; done这里面的关键点有两个:一个是for f in app_*.conf,Shell会先把通配符展开成所有匹配的文件名,然后逐个赋值给变量f;另一个是${f%.conf},这是Shell参数扩展的经典用法,表示从变量f的结尾去掉.conf这个后缀。两下一组合,就实现了"改名并追加后缀"。这种操作你要是靠人肉做,一次两次还行,多了准出错,而且完全没办法回溯。
写到这我得多说一句:能用循环批量干的事,千万别手搓。不只是重命名,批量创建目录、批量压缩日志、批量修改权限,都是一个循环+一个核心命令的事。学Linux命令,第一个要养的思维就是"怎么让机器替我做重复劳动"。
2.2 "删库"之前问自己三次:rm的安全细节
rm -rf这命令,江湖人称"跑路命令"。我见过不止一个同事,在/目录下或者HOME目录下,脑子一抽就敲了rm -rf *,然后就是漫长的沉默。我自己的纪律是:生产环境禁用裸rm -rf,再怎么着急,也得先把目录cd进去,ls看一眼,再删。这不是胆小,这是对自己负责。
但这不代表不能用rm,而是要讲究方式方法。比如我只想删掉目录下所有.tmp文件,但保留其他东西:
rm -i *.tmp-i参数会在删除每个文件前问一次,嫌烦的话用find配合-delete更安全:
find ./ -name "*.tmp" -type f -delete用find的好处是你能先不加-delete跑一遍,看看它到底会匹配到哪些文件,确认无误了再把-delete加上。这个"先预览后执行"的思路,在处理批量删除、批量修改时简直是保命符。
另外真心建议个人电脑或测试机上装个trash-cli,它会把删除的文件挪到回收站而不是直接抹掉。命令敲成trash file.txt,哪怕手滑了还能救回来。生产环境当然不推荐,但在你本地环境这层保护很有价值。在删除这件事上,多一道确认、多一层回收,都是值得的。
2.3 找文件不只是find:几个参数让你少敲一半命令
find是Linux下最被低估的命令之一。很多人只会用find / -name "xxx",然后抱怨慢。慢就对了,你从根目录全盘扫描,不慢才怪。正确的打开方式是先缩小范围。
举个例子,我想找/home下所有属于www用户、大小超过500M的日志文件:
find /home -user www -type f -size +500M -name "*.log"这里-user www按属主过滤,-size +500M过滤大小,-name "*.log"过滤文件名。三个条件一叠加,结果就非常精准了。更实用的是按时间找,比如"最近7天被修改过的PHP文件":
find /var/www -type f -name "*.php" -mtime -7如果想找的是"7天前都没再动过的临时文件",把-mtime -7换成-mtime +30(30天前修改)就行。再配合ls -lh或者-exec ls -lh {} \;看一眼大小和日期,基本就能定位到哪些是历史遗留垃圾。
我有个习惯:每当服务器磁盘告警,第一反应不是去du -sh *一个个看,而是用find按-size +1G筛一遍。大多数情况下,罪魁祸首都是几个超大的日志文件或者备份包,直接逼到案发现场,效率高得不是一点半点。
2.4 文件对比与同步:diff和rsync,一对黄金搭档
排查问题的时候,我们经常要对比"线上配置"和"测试配置"到底差在哪。diff这时候比人眼靠谱得多:
diff -u nginx.conf.bak nginx.conf-u输出统一格式,能直接看出哪些行被修改、新增、删除。如果你用的是IDE或者代码编辑器,这格式还能直接被理解成"变更视图"。有时候懒得登录服务器,我会先在本地把文件拉下来再diff,一个道理。
而说到同步,rsync是当之无愧的神器。我同步代码到测试服务器常用:
rsync -avz --delete ./dist/ user@server:/var/www/html/解释一下:-a归档模式保留权限、时间戳这些属性,-v显示详情,-z传输时压缩,--delete让目标目录里多余的文件也删掉,保证两边完全一致。最爽的是它支持断点续传和增量同步,传一个大目录中断了,重新跑一遍会跳过已传完的部分,比干脆利落地覆盖整个目录不知道高到哪里去了。
不过用--delete要格外小心,它会把目标目录清成和源一模一样。我建议第一次同步的时候先加个--dry-run(也就是-n参数)跑一遍,看看它到底打算删哪些文件、传哪些文件,心里有数了再动真格。
3. 文本处理三件套:grep、awk、sed的实战场景
3.1 grep:从"搜索关键词"到"日志里的福尔摩斯"
grep是每个用Linux的人最先接触的命令之一,但多数人停留在grep "error" log.txt这个水平。我觉得真正拉开效率差距的是这几个进阶用法。
第一个是上下文匹配。日志报错从来不是孤立的一行,错误日志的堆栈往往在报错行前后几十行。直接grep -C 5 "Exception" app.log,能把匹配行的前后5行都打出来,完整还原现场。-A是向后取,-B是向前取,结合着用。
第二个是多条件组合。查"订单系统在支付回调里报超时"的日志,直接用扩展正则:
grep -E "支付|timeout|order_" app.log | grep "回调"用管道把第一次筛选的结果再筛一遍,比写一条复杂正则容易理解得多。这里-E表示用扩展正则,|在正则里表示"或"。
第三个是只输出匹配部分。有时候日志里每行都带时间戳、线程号、日志级别,而我只关心里面的IP地址,那就用-o参数:
grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" app.log | sort | uniq -c | sort -nr这一条组合命令的含义是:先把每行里长得像IP的部分单独抽出来,然后排序,统计每个IP出现次数,再按次数从高到低排。它解决的是一个特别典型的问题——"到底是哪个IP在疯狂请求我们的接口",一眼就能看出来。这串管道我愿称之为日志排查最常用组合拳,没有之一。
3.2 awk:日志统计利器
如果说grep是筛子,那awk就是瑞士军刀。它能按列拆分、能累加统计、能做条件判断,是写命令行的"内联脚本语言"。
最常见的场景是分析Nginx访问日志。日志格式类似:
127.0.0.1 - - [01/Jan/2024:12:30:45 +0800] "GET /api/user HTTP/1.1" 200 532其中第1列是客户端IP,第9列是状态码,第10列是响应字节数。想统计每个IP产生了多少请求,平均返回多少字节:
awk '{ ip[$1]++; bytes[$1]+=$10 } END { for (i in ip) print i, ip[i], bytes[i]/ip[i] }' access.log这个脚本的逻辑很好理解:每读一行,以第一个字段(IP)为下标,请求数加一,同时把第10字段(字节数)累加进去。全部处理完后,遍历打印每个IP的请求数和平均字节数。这种一行命令顶得上你写几十行Python脚本的效率。
如果想筛出状态码是500的请求数占总请求数的比例:
awk '$9==500 {count500++} {total++} END {print count500/total*100"%"}' access.log实际用下来,awk的威力在于它把字段遍历和统计聚合揉到了一条命令里。你不需要写循环、定义变量、处理文件格式,只要声明"每行的第几列怎么处理",剩下的它全包了。这就是命令行的魅力——简短的表达,强大的能力。
3.3 sed:批量文本替换的好帮手
sed对我来说主要干两件事:一个是批量替换,一个是精准打印某段内容。批量替换的经典场景是:配置文件里把旧的数据库地址换成新的。
sed -i 's/192.168.1.100/192.168.1.200/g' config.properties-i表示原地修改(直接改文件,备份加-i.bak更保险),s是替换命令的结构,g代表全局替换(不写的话每行只替换第一处匹配)。这个命令在改配置文件、批量替换代码里的某个变量名时,能省下一大截时间。
精准打印某段内容也很好用。比如一个几百兆的日志文件,你想看第1000到1010行发生了什么:
sed -n '1000,1010p' app.log-n是"不自动打印",p是"打印匹配范围",两个参数配合就是"我只想看我指定的那几行"。这比head -1010 | tail -11来得直观。
但这里要特别提醒:sed -i是危险操作,因为它直接改源文件且不可逆。我的习惯是先用不带-i的替换跑一遍,把输出目测一遍确认没问题,再带上-i执行。如果是重要配置文件,先cp一份备份再动手,养成肌肉记忆。
3.4 管道组合的思路:先筛、再切、最后统计
上文已经涉及好几次管道了,但值得单独说一下设计思路。我总结的套路是:先定位范围,再提取字段,后聚合统计,最后排序展示。
第一步,用grep或sed缩小到感兴趣的行;第二步,用awk或cut把这些行里的关键字段切出来;第三步,用sort、uniq -c、awk做统计;第四步,用sort -n排出顺序。这个思路适配绝大多数文本分析需求。
举个完整例子,统计某个时间段内每个接口被调的次数,并按次数排序:
grep "2024:10:" access.log | awk '{print $7}' | sort | uniq -c | sort -nr | head -20第一段筛出上午10点的日志,第二段取出URL路径字段,第三段排序,第四段统计去重(uniq -c),第五段按次数降序,最后只取前20个。这一串下来就是一张现成的"接口热门榜",整个过程不用写脚本不用下载文件,一条命令的事。平时多积累这种套路,遇到具体问题时就能下意识地组合起来,不用翻书。
4. 性能排查:Linux资源监控命令组合
4.1 一上来CPU飙高,我到底该看什么
服务器报警CPU使用率100%,我建议不要一上来就盯着top看,因为top显示的是进程维度的快照,信息不够纵深。更有效的路径是:先用top找出嫌疑进程,再用pidstat看线程,最后定位到具体代码逻辑。
top敲进去,按P键可以按CPU使用率排序,一眼扫到最上面的进程PID。这一步其实已经解决了一半问题——你知道了是哪个进程在吃CPU。
然后需要看这个进程里的线程情况:
pidstat -t -p 12345 1 5-t显示线程维度的统计,-p 12345指定进程,1 5表示每1秒采样一次、共采5次。它能告诉你这个进程内部,具体是哪个线程在拼命烧CPU。
如果你是Java应用,还可以用jstack把线程快照打出来,和pidstat看到的线程号换算成十六进制去对。但如果你不是Java,没关系,至少排查链路是通用的:进程 → 线程 → 代码,层层下钻,每一步都在缩小嫌疑范围。整个流程走下来,一般几分钟就能从"CPU飙高"定位到具体某个方法或某段逻辑。
vmstat也是个容易被低估的命令。它直接查看系统层面的CPU、内存、IO概况。有个参数组合特别适合复盘瓶颈:
vmstat 1 10每秒输出一行,持续10行。重点看r列(运行队列长度)、us列(用户态CPU)、wa列(I/O等待)。如果r长期大于CPU核数,说明任务排队严重;如果wa很高,说明瓶颈可能在磁盘而不是CPU。
4.2 free到底该怎么看?重点不是可用内存
free -h命令人人会敲,但很多人只会看倒数第二行available。我的经验是:别被Used很高吓到,也别盲目追求Available很高。Linux的内存策略是"能缓存就缓存",你看到的used里很大一部分其实是page cache,也就是文件缓存,这些内存在程序需要时是可以立刻释放的。
判断内存是否真吃紧,我一般看两个东西:available是不是快没了(这才是真正能分配给新进程的内存),以及有没有明显的swap使用。swap一旦用起来,说明物理内存真的不够了:
free -h如果发现swap用了不少,还得配合看看到底是哪个进程在占用:
ps aux --sort=-%mem | head -10按内存占用排序,前10个进程名单一列,谁是大头一目了然。这套组合下来,"内存够不够、谁吃的、要不要优化"三连问就有着落了。
4.3 磁盘IO才是很多性能问题的"隐形凶手"
很多服务变慢,CPU和内存看着都正常,实际上瓶颈在磁盘。最简单的验证方式是用iostat看一下%util:
iostat -x 1 3%util接近100%说明磁盘设备已经处于饱和状态。这段时间经常能看到iowait飙高,但光看wait不够,iostat -x能看到每个设备层面的读写速率和队列长度。如果确认是某个设备忙,可以进一步找是哪个进程读写的,iotop工具能实时显示每个进程的磁盘读写带宽:
iotop -o -P-o只显示正在读写I/O的进程,-P只显示进程不显示线程,输出清爽得多。实际排障中,我遇到过几次慢查询导致大量磁盘读、从而拖垮整个数据库服务的情况,都是通过这条链路定位到具体进程再去优化SQL的。
4.4 网络连接排查:ss和netstat怎么选
排查网络连接,老一点的教程会让你用netstat,但新一点的系统我更推荐ss,它更快、信息更全。查当前所有监听端口:
ss -lntp-l只看监听状态,-n不反解域名(直接显示IP,速度快很多),-t只看TCP,-p显示对应进程。比如你想知道80端口上到底是哪个服务在跑,它直接给你进程名和PID。
如果服务器连接数异常高,比如出现大量TIME_WAIT,会影响新连接的建立。排查方式:
ss -s这条输出的是汇总统计,TCP各状态的数量一目了然。如果TIME_WAIT上万,说明服务端主动关闭连接太多,可能需要调整内核参数或优化业务代码。这里就不展开内核调优了,但排查思路是一样的:从汇总里发现异常,再下钻到具体连接。
4.5 一次CPU飙高的完整排查实录
讲个实际案例。有次某项目上线后,监控不停报CPU 100%,但奇怪的是业务量并没有增长。我按顺序走了这么几步:
第一步top按P排序,看到一个Java进程占了350%。第二步pidstat -t -p看到某个线程一直在跑。第三步把线程号转十六进制,jstack抓线程栈,发现是在执行一个正则匹配的方法。第四步查代码,发现那个正则在处理一段特殊字符串时触发了灾难性回溯。
问题定位到代码层级,后面的事就简单了——优化算法、上线、观察CPU降下来了。整个排查过程如果只会在某个环节敲一个命令,走不到最后。但当命令串成链路,每个环节都在缩小范围,排查高手的价值正在于此。所以说,学命令不能只学单点,要学整条链路。
5. 进程、会话与服务管理:从裸奔到规范化
5.1 查进程、杀进程:ps的精髓在"找"
ps命令参数特别多,说实话我不建议全背,但有两套组合必须刻进DNA里。第一个是看全量进程并排序:
ps -ef简明直观,带父进程PID,能看出进程之间的父子关系。第二个是按关键字快速找:
ps -ef | grep java但注意,这条命令会把grep自己那一行也匹配进去,看着有点碍眼。更优雅的写法是pgrep -af java,直接返回进程号和完整命令行,不会混入多余输出。
找僵尸进程也是一项经典操作。僵尸进程就是子进程结束了但父进程没回收它,这种进程杀不掉(它已经死了),只能处理它的父进程。排查方式:
ps -ef | grep defunct如果僵尸进程较多,说明某个父进程没有正确处理子进程退出状态,得从代码层面解决,光杀是没用的。这个知识点在面试时也算个加分点,实操中排查孤儿进程链也挺有用。
5.2 kill不是"杀掉"这么简单
kill命令的本质是向进程发送一个信号,而不同的信号决定了进程会怎么回应。常用的三个信号得搞清楚:
kill -9 PID # 强制杀死,不可被捕获,慎用 kill -15 PID # 默认信号,请求进程退出,可被捕获做清理工作 kill -1 PID # 让进程重新加载配置,比如nginx、sshd我见过不少新手一遇到杀不掉的进程就kill -9,简单粗暴。但实际上-9相当于直接"切断电源",进程没机会清理临时文件、释放锁、记录状态,如果是有状态服务,很容易留下脏数据,下次启动直接就起不来了。正确的顺序是先用-15,给进程一点时间做善后;过几秒还没退出再考虑-9。
重载配置用-1是个特别实用的技巧,比如改了Nginx配置又不想中断服务,一条kill -1 $(cat /var/run/nginx.pid)或者nginx -s reload就能热加载,不用重启服务。这在生产环境里是刚需操作。
5.3 会话与后台运行:nohup和screen的组合
用SSH连到服务器跑一个长任务,直接关终端会把任务一起带走,这个坑我早期踩过无数次。最简单的规避方式是用nohup:
nohup sh long_task.sh > output.log 2>&1 &拆开解释一下:nohup让命令忽略挂断信号,> output.log把标准输出写进文件,2>&1把错误输出也合并进同一个文件(否则报错你看不到),最后的&把进程放到后台。这套写全了,才是一个合格的后台任务启动命令。如果只写nohup command &而不重定向输出,它会生成一个nohup.out文件,混乱不说,还可能占满磁盘。
但nohup有一个天生的短板:任务启动以后,你就没法再回到那个会话里看了。想跟踪进度怎么办?只能读日志文件。更优雅的方案是用终端复用工具,我最常用的是screen:
screen -S mytask # 在里面跑你的长任务 # 按 Ctrl+A 然后按 D 把会话脱离 screen -r mytask # 需要时重新接回这个会话这种"开个虚拟终端、跑任务、关掉连接、回头再看"的模式,做编译、跑批处理、远程部署时都舒服得多。同类工具还有个tmux,功能更强,快捷键体系不一样,顺手就行。
5.4 systemctl:现在的主流服务管理
新一点的发行版都换成了systemd,服务管理的标准姿势是:
systemctl status nginx # 看服务状态 systemctl start nginx # 启动 systemctl enable nginx # 设为开机自启 systemctl restart nginx # 重启 journalctl -u nginx -f # 实时看这个服务的日志我最常用的是journalctl -u nginx -f,它直接把服务日志接上了,都不用去翻/var/log目录。这在排查"服务怎么又挂了"时效率极高,服务启动时的报错信息全都集中在一起。顺便提醒,每次改完配置一定要restart或者reload,不要以为改完文件就生效了——这也是新手常掉的坑。
6. 网络排查:命令组合拳
6.1 从ping不通到定位具体环节
网络问题排查是有套路的。我习惯按这个顺序来:先判断是不是链路不通,再判断是哪一层有问题。
第一步,ping一下目标地址:
ping -c 4 www.example.com能通就说明网络链路是通的(至少ICMP通)。如果ping不通,可能是防火墙、路由或者对端禁ping等。下一步查路由是ip route,查自己的IP是ip addr,层层排查。以前大家习惯用ifconfig,现在新系统更好用的是ip命令套件,信息更全、输出更规范。
这里要特别提一句:ping通了不代表应用层就正常。有时候网络通但端口不通,就需要用到下面要讲的命令。
6.2 测端口和接口:curl是排查应用层的好帮手
端口连通性测试我一般用nc或telnet:
nc -vz 192.168.1.10 8080-v显示详细过程,-z表示只探测端口不发送数据,几秒钟就能判断端口是否开放。
如果是HTTP接口的排查,curl是首选。常用参数组合:
curl -i -X POST -H "Content-Type: application/json" -d '{"key":"value"}' http://localhost:8080/api/test-i显示返回的响应头,-X指定请求方法,-H添加请求头,-d附带请求体。排查接口报错时,我一般先加-v看完整握手和请求发送过程。它能显示TLS握手细节、是否走了代理、响应头里有没有奇怪的跳转,这些都是浏览器开发者工具很难给出的信息,尤其是在服务器本机测试时,curl几乎是不二之选。
6.3 DNS排查:解析慢或解析错时怎么办
域名解析是网络访问的第一步,出问题往往表现为"网站打不开但IP能通"。排查DNS我常用dig:
dig www.example.com它会把完整的DNS解析过程列出来,包括哪个DNS服务器响应、解析耗时、查询结果。dig +trace能一步步跟踪从根域名服务器到最终结果的完整链路,如果某一步超时了,问题就出在那一环。老命令nslookup也可以用,但其实dig输出更清晰、更适合排障。
如果确定是DNS问题,先检查系统的解析配置/etc/resolv.conf,看看nameserver指向哪里,再对比一下其他环境是否能正常解析。很多内网环境的怪问题,最后都出在DNS配置指错地方。
6.4 抓包分析:tcpdump的简单用法
有些网络问题靠ss、curl判断不出来,就得抓包看了。比如接口响应慢,你想确认是客户端等得久,还是服务端回复得慢,用tcpdump抓一下端口上的流量,最直观:
tcpdump -i eth0 port 8080 -w /tmp/capture.pcap-i指定网卡,port过滤端口,-w把原始包保存下来,然后用Wireshark打开分析。
如果你不想装图形工具,tcpdump直接输出也能看个大概:
tcpdump -i eth0 host 192.168.1.10 and tcp port 80在服务器端抓包能理清很多"玄学问题":SYN包有没有到?三次握手有没有完成?数据包是不是分片了?应答是不是延迟了?这些都是应用层看不到的底层信息。出现网络问题时,抓包是最后的"实锤"手段,有些结论光靠猜是猜不出来的。
6.5 一次"网站白屏"的排查全流程
我之前遇到过一个案例:站点突然白屏,但服务器负载看着不高。我这边排査的逻辑是这样——先看服务进程是否存活:
systemctl status nginx活着。然后看本机端口监听:
ss -lntp | grep :80正常。接着curl -I http://127.0.0.1看本机访问,返回200。本机正常,那问题可能出在外部链路上。再curl -I公网地址试试,结果超时。最后抓包发现tcpdump里SYN包到了,但回包没出去,顺藤摸瓜发现防火墙策略把出方向某个段给挡了。
这个案例想说明的是:排障不是碰运气,而是利用命令一点点缩小范围。每一层都有对应工具,每一条链路都有该看的信息,掌握这些命令等于给自己装了一副排查问题的望远镜和显微镜。
7. 把命令串成脚本:从"敲命令"到"自动化运维"
7.1 用一条命令备份或迁移数据
理解了单条命令,下一步就该试试把它们串成脚本,哪怕只是一行综合命令。最典型的就是数据库备份:
mysqldump -u root -p db_name | gzip > /backup/db_$(date +%Y%m%d_%H%M%S).sql.gzmysqldump导出的数据直接通过管道流给gzip压缩,文件名里带时间戳。这样既省了磁盘空间,又自动区分了备份时间点。顺手还能配合find做保留策略,比如只保留最近7天:
find /backup -name "*.sql.gz" -mtime +7 -delete一条命令完成清理,不用手动清理攒了好几个G的旧备份。
7.2 日志切割与清理自动化
日志膨胀是每台服务器都会遇到的问题。除了用logrotate(系统自带的日志轮转机制),我们也可以手写一个简单的清理脚本思路:每天凌晨用find把超过30天、大于500M的日志删掉,再把昨天日志压缩归档。
find /var/log/nginx -name "*.log.*" -mtime +30 -delete find /var/log/nginx -name "*.log" -mtime +1 -exec gzip {} \;第一条删除超过30天的旧日志,第二条把昨天的access.log压缩成access.log.gz。加个cron定时任务,磁盘告警的烦恼能减少一大半。这些命令单独看不难,但组合起来就形成了完整的运维策略。
7.3 写一个服务器健康检查的Shell脚本
我习惯把日常检查做成一个小的Shell脚本,每天自动跑一遍输出结果。脚本核心逻辑无非是把前面讲过的命令串起来:
#!/bin/bash echo "===== 系统负载 =====" uptime echo "===== 内存使用 =====" free -h echo "===== 磁盘占用 TOP5 =====" df -h | sort -k5 -n | tail -5 echo "===== 高CPU进程 TOP5 =====" ps aux --sort=-%cpu | head -6再简单点,可以直接用alias把常用组合命令收成快捷键。比如我本机配了:
alias keys='ps -ef --sort=-%cpu | head -20' alias myip='ip addr show | grep inet'配置在~/.bashrc里,source一下生效。这种把高频命令变成顺手快捷键的习惯,长期积累下来,效率差距非常可观。
7.4 Shell脚本的几点提醒
写Shell脚本踩过的坑,我总结了几个:第一,变量赋值等号两边不能有空格,name = "xxx"会报错,写成name="xxx"才对。第二,引用变量尽量用双引号包起来,比如echo "$name",否则路径里有空格时会出问题。第三,判断命令返回值,用$?或者直接:
if command; then echo "success" else echo "fail" fi这种写法比把$?存下来再判断直观得多。第四,脚本开头一定加set -e,表示只要某条命令返回非零就直接退出,避免在错误状态下继续执行导致更严重的后果。
8. 常见问题与排查技巧实录
这部分我把实际运维中经常碰到的几个典型问题整理成一个速查表,方便各位在处理类似状况时能快速定位方向。表格里给的是排查命令和解决思路,但真正定位问题往往需要组合使用,以下几个案例应该能让这个表格变得立体起来。
| 现象 | 一般先查什么 | 常用命令 | 常见原因与解决思路 |
|---|---|---|---|
| 磁盘空间不足 | 找出占空间的目录 | df -h、du -sh /* 2>/dev/null | sort -hr | head -10 | 日志文件过大、旧包未清理,用上文find命令清理或调整日志策略 |
| CPU持续100% | 找出吃CPU的进程 | top(按P排序)、pidstat -t -p PID | 业务代码死循环、正则回溯、GC线程或虚拟机异常,下钻线程抓栈分析 |
| 命令找不到 | 确认路径和安装情况 | which nginx、echo $PATH | 环境变量问题或软件未安装,重新配置PATH或安装软件包 |
| 端口被占用 | 找出占用进程 | ss -lntp | grep :8080、lsof -i:8080 | 旧服务未退出或同端口进程冲突,确认后处理对应进程 |
| 网络连接数异常高 | 查连接状态分布 | ss -s、ss -ant | awk '{print $1}' | sort | uniq -c | TIME_WAIT过多或连接泄漏,调整内核参数或优化代码长连接管理 |
| 文件无法删除 | 确认权限和文件类型 | ls -l、lsattr | 权限不足或存在不可变属性,修改权限或用chattr去掉属性 |
这个表格只是入口。实际排查问题,我始终强调的是链路思维:从现象反推可能出问题的环节,再用对应命令验证。比如"磁盘满是现象",可能的原因有日志膨胀、备份文件堆积、数据库临时文件等等。每条线索都会引导你用不同的命令去确认,这就是命令行技能的真正价值。
9. 写在最后的几点实在心得
文章写到这,核心内容已经讲得差不多了,最后分享几个我用Linux命令多年攒下来的心得。
第一,得学会看帮助文档。别一遇到不认识的命令就百度,先man 命令或命令 --help,绝大多数用法参数都写清楚了。英文不好没关系,看个大概结构就够了,查多了自然熟悉。尤其是man里的EXAMPLES部分,基本是官方给的实用案例,比看网上二手教程靠谱得多。
第二,用一个命令前,先想想可能产生什么后果。尤其是涉及删除、覆盖、批量修改的命令,一定要想清楚影响范围再动手。生产环境上操作前,备份永远是合格的选择。我给自己定的规矩是:高危操作在回车前先停下来看一眼、确认一遍,这个习惯帮我躲过了好几次灾难。
第三,多记录自己的组合命令。每当摸索出一条好用的命令组合,我会把它记到笔记里,注明应用场景。时间久了,这就是你自己的命令手册,比任何教程都实用。很多看起来复杂的运维操作,不过是几条命令组合体,记熟了就是肌肉记忆。
第四,别怕耗时去理解原理。比如为什么grep比编辑器搜索快?因为它只做流式处理,不需要把整个文件载入内存。为什么rsync适合传大文件?因为它能断点续传而且只传差异部分。弄懂了这些底层机制,你就知道什么场景该用什么工具,而不是背参数。这一点,比记住几百条命令重要太多。
玩转Linux命令,本质上是在学习一种"用计算机的思维解决问题"的方式。它让你学会组合、抽象、自动化、以及带着链路意识去排查。这条路没有终点,但你会越来越顺,越来越有手感。希望这篇实战分享,能给你一些切实的参考。