1. 这不是命令清单,而是一份Linux运维现场的“生存手记”
你打开终端,敲下ls,系统卡住三秒才返回;半夜收到告警,df -h显示根分区98%满,但du -sh *加起来却只有60G;想查某个服务为什么起不来,systemctl status xxx只告诉你“failed”,日志里却全是Failed to start xxx.service的循环废话——这些不是教科书里的练习题,是凌晨两点你盯着黑底白字屏幕时的真实心跳。我做Linux运维十多年,带过三个不同规模的线上环境,从单台物理服务器跑PHP小站,到管理上千节点的混合云集群,踩过的坑、抄过的作业、写废的脚本摞起来比《鸟哥的Linux私房菜》还厚。这份“Linux运维实用100条命令”,不是网上随手搜来的冷饭合集,而是我把十年间在真实生产环境里反复验证、高频调用、能救命的命令,按场景重新归类、拆解原理、标注陷阱后整理出来的实战手册。它不讲man ls里每个参数的定义,而是告诉你为什么ls -lSh比ls -lt更适合快速定位大文件;不罗列find所有语法变体,而是教你用find /var/log -name "*.log" -mtime +30 -delete删日志前,必须先加-print看一眼再执行;不堆砌awk的高级用法,而是用awk '{sum += $3} END {print sum}'统计某列总和时,如何避免空行导致计算错误。适合刚转行的新人当速查地图,也适合老手在交接文档里直接贴进运维SOP。它解决的不是“怎么用”,而是“为什么这么用才不会翻车”。
2. 命令设计逻辑:从“能跑”到“稳跑”的三层过滤
2.1 第一层过滤:剔除“理论正确但生产危险”的命令
很多教程推荐rm -rf /tmp/*清临时目录,但实际运维中,我见过三次因此误删正在被进程锁定的socket文件,导致Nginx无法reload。真正安全的做法是find /tmp -type f -mtime +7 -delete,用-type f排除目录和设备文件,用-mtime +7确保只删七天前的旧文件。同理,kill -9常被滥用,但对Java应用,kill -15(SIGTERM)才是标准流程,它会触发JVM的shutdown hook,让Spring容器优雅关闭连接池、释放资源;只有kill -15超时无响应时,才用kill -9强杀。这种取舍背后是运维的底层逻辑:稳定性优先于速度,可追溯性优先于简洁性。所以这份清单里所有带-f(force)或-9的命令,都强制要求搭配前置校验步骤,比如删用户前必先id username确认存在,改配置前必先cp config.conf config.conf.bak_$(date +%Y%m%d)备份。
2.2 第二层过滤:聚焦“高频、高危、高价值”三角区
运维命令浩如烟海,但真正决定效率的往往是那几十个。我们按三个维度打分:
- 高频:每周至少执行3次以上,比如查磁盘、看进程、查网络连接;
- 高危:操作失误会导致服务中断或数据丢失,比如
dd、mkfs、truncate; - 高价值:一条命令能替代多步操作,比如
journalctl -u nginx --since "2 hours ago" | grep "502"直接定位两小时内Nginx的502错误,比翻日志文件快十倍。
最终入选的100条,全部落在这个三角区交集内。例如ss -tuln替代netstat -tuln,不仅因为更快(ss基于kernel socket API,netstat需遍历/proc),更因它默认不反向解析DNS,避免netstat在DNS故障时卡死;再如rsync -avz --delete同步目录,-a保留权限时间戳,-v输出详细过程便于审计,--delete确保目标端与源端完全一致——这三个参数组合,解决了备份一致性这个核心痛点,比单纯cp -r可靠得多。
2.3 第三层过滤:嵌入“防呆设计”与“上下文感知”
真正的实用命令,必须自带容错机制。比如查内存,新手常free -h,但free的available列才是可用内存(已扣除内核缓存等),而used列容易误导;老手则用cat /proc/meminfo | awk '/MemAvailable/{print $2/1024/1024 " GB"}'直接算出GB单位的可用内存。又如批量改文件名,rename 's/old/new/g' *.txt看似简洁,但若文件名含空格或特殊字符会崩溃;更稳妥的是for file in *.txt; do mv "$file" "${file//old/new}"; done,用双引号包裹变量,//全局替换,规避shell解析陷阱。这种“防呆”不是过度设计,而是把十年间因空格、编码、权限导致的报错,提前固化成命令结构。每条命令都像一个微型程序,有输入校验(如[ -f "$file" ] && ...)、有异常处理(如|| echo "fail")、有结果验证(如echo $?检查上条命令退出码)。
3. 核心命令详解:按实战场景分组,附原理与避坑点
3.1 磁盘与文件系统:从“空间告警”到“根因定位”的完整链路
当监控报警“/var分区使用率>95%”,第一反应不该是df -h,而是df -i查inode是否耗尽——我曾处理过一个案例:df -h显示/var仅用40%,但df -i发现inode使用率99%,原因是日志轮转脚本bug,生成了数百万个0字节的.log.1空文件,du统计大小为0,却占满inode。此时find /var -xdev -type f -size 0c | head -100 | xargs rm -f才能根治。以下是磁盘问题的黄金组合:
快速定位大文件:
du -sh /* 2>/dev/null | sort -hr | head -20
原理:du -sh以人类可读格式统计各目录大小,2>/dev/null屏蔽权限拒绝错误(如/proc),sort -hr按数值逆序排序(-h识别K/M/G单位)。注意du默认递归子目录,若只想看一级目录,必须加/*而非.。实操心得:在/var下执行时,先cd /var再运行,避免du扫描整个根目录拖慢速度。安全清理日志:
journalctl --disk-usage查journald占用,journalctl --vacuum-size=500M限制日志总大小
原理:systemd-journald日志默认无限增长,--vacuum-size会自动删除最旧日志直到满足大小。比手动rm /var/log/journal/*安全,因journald可能正写入文件。避坑:--vacuum-time=2weeks按时间清理更常用,但需确认业务日志留存策略,金融类系统通常要求90天以上。修复只读文件系统:
dmesg | grep -i "ext4.*error"查内核错误,e2fsck -f /dev/sda1强制检查
原理:文件系统只读常因ext4元数据损坏触发保护,dmesg抓取实时内核日志比/var/log/messages更及时。e2fsck必须在卸载状态下运行,若根分区损坏,需从Live CD启动。关键参数:-y自动确认所有修复,-c检查坏块(机械硬盘必备)。我试过一次,e2fsck -f -y /dev/sda1修复后,mount -o remount,rw /即可恢复写入。监控实时IO压力:
iostat -x 1 3(-x扩展统计,1秒间隔,3次)
关键指标解读:%util超80%说明磁盘饱和;await(平均等待毫秒)>10ms表示响应延迟;svctm(服务时间)应远小于await,若接近说明队列堆积。对比iotop(进程级IO),iostat更轻量,适合脚本集成。实测:在数据库写入高峰,await飙升至200ms,%util达100%,但svctm仅5ms,确认是IO队列过长,非磁盘硬件故障。
3.2 进程与服务管理:从“进程僵死”到“服务自愈”的闭环操作
服务异常时,ps aux | grep nginx只是起点。真正的排查要穿透三层:进程状态、资源占用、依赖关系。比如Nginx 502错误,表面是上游服务挂了,但根源可能是其进程被OOM Killer干掉。此时dmesg -T | grep -i "killed process"能直接看到内核日志:“Killed process 12345 (java) total-vm:2048000kB, anon-rss:1536000kB, file-rss:0kB”。以下是服务管理的核心命令链:
精准杀进程:
pkill -f "python3 /opt/app/main.py"而非kill $(pgrep -f "main.py")
原理:pgrep -f匹配完整命令行,但pgrep本身可能被误匹配(如pgrep -f pgrep会杀自己);pkill -f更安全,且支持信号指定,如pkill -f -SIGUSR2 "nginx"平滑重启。避坑:pkill默认匹配进程名,加-f才匹配命令行,务必确认。查看进程打开文件:
lsof -p 12345 | wc -l统计句柄数,lsof -i :8080查端口占用
原理:lsof(list open files)是Linux万能诊断工具,一切皆文件——网络连接、管道、设备都是文件。-p按PID过滤,-i按网络信息过滤。实操技巧:lsof -iTCP -sTCP:LISTEN只看TCP监听端口,比netstat更精准;lsof +D /tmp递归查/tmp下所有打开文件,定位被占用的临时文件。服务依赖分析:
systemctl list-dependencies --reverse nginx.service查谁依赖Nginx
原理:systemd的依赖树是双向的,--reverse显示反向依赖(即哪些服务需要Nginx先启动)。这在微服务架构中极关键——若A服务依赖B,B依赖C,C挂了,A可能报“连接拒绝”而非“服务未启动”。配合systemctl show nginx.service | grep -E "(Wants|After|BindsTo)"可深度分析依赖关系。内存泄漏初筛:
ps aux --sort=-%mem | head -10找内存大户,pstack 12345查Java线程栈
原理:ps的--sort=-%mem按内存百分比降序,-表示降序。对Java应用,pstack比jstack更底层,无需JDK,直接读取进程内存映射。避坑:pstack需进程未被ptrace附加(如被gdb调试时会失败),此时改用jstack -l 12345 > stack.log。
3.3 网络诊断:从“连不上”到“为什么连不上”的逐层穿透
网络问题排查像剥洋葱:物理层→链路层→网络层→传输层→应用层。ping只能验证ICMP通路,curl -v http://api.example.com才能看到HTTP握手全过程。以下是网络诊断的黄金路径:
绕过DNS查真实IP:
dig +short api.example.com @8.8.8.8(用Google DNS)
原理:dig比nslookup更可靠,+short精简输出,@8.8.8.8指定DNS服务器,排除本地DNS缓存污染。对比host api.example.com,dig能显示TTL、权威服务器等细节。实操:当curl报“Could not resolve host”,先dig确认DNS是否正常,再curl -v --resolve "api.example.com:80:192.168.1.100" http://api.example.com强制解析到指定IP,隔离DNS问题。检测端口连通性:
timeout 5 bash -c '</dev/tcp/api.example.com/443' && echo "OK" || echo "FAIL"
原理:bash内置的/dev/tcp/host/port是纯shell方案,无需安装telnet或nc。timeout 5防卡死,&&/||实现条件判断。比nc -zv api.example.com 443更轻量,适合脚本集成。避坑:某些精简版busybox shell不支持/dev/tcp,此时用echo > /dev/tcp/host/port 2>/dev/null && echo OK。抓包分析协议:
tcpdump -i eth0 port 8080 -w /tmp/app.pcap -c 1000(抓1000包)
原理:tcpdump是网络分析基石,-i指定网卡,port过滤端口,-w写入文件,-c限制数量防磁盘爆满。关键技巧:-s 0捕获完整包(默认只抓前68字节),-A以ASCII打印内容(适合HTTP明文)。我处理过一次API超时,tcpdump抓包发现客户端发了SYN,服务端回了SYN-ACK,但客户端没发ACK——确认是客户端防火墙拦截,非服务端问题。路由追踪优化:
mtr -r -c 100 api.example.com(-r报告模式,-c100次)
原理:mtr是traceroute+ping的结合体,-r生成汇总报告,显示每跳丢包率和延迟。比traceroute更能暴露网络抖动。实操:当ping延迟高,mtr能定位是第几跳开始丢包,是运营商骨干网还是IDC机房问题。注意mtr需root权限,普通用户用mtr --no-dns禁用DNS解析提速。
3.4 安全与权限:从“最小权限”到“攻击痕迹”的主动防御
运维安全不是装防火墙,而是让每个操作都符合最小权限原则。chmod 777是毒药,setfacl -m u:deploy:r-x /opt/app才是解药。以下是安全加固的关键命令:
审计敏感操作:
ausearch -m avc -ts recent | aureport -f -i查SELinux拒绝事件
原理:ausearch查audit日志,-m avc过滤SELinux访问控制事件,-ts recent查最近事件。aureport生成可读报告。当Web服务报“Permission denied”但权限明明正确,很可能是SELinux阻止。setsebool -P httpd_can_network_connect 1开启HTTPD网络连接即可。避坑:setsebool的-P参数永久生效,不加则重启失效。检查异常登录:
lastb -n 20(-n显示最近20条失败登录)
原理:lastb读取/var/log/btmp(失败登录日志),比grep "Failed password" /var/log/secure更直接。配合faillog -u username查特定用户失败次数。实操:发现lastb中大量同一IP的root登录失败,立即iptables -A INPUT -s 192.168.1.100 -j DROP封禁,并检查/etc/ssh/sshd_config是否禁用root密码登录(PermitRootLogin no)。文件完整性校验:
rpm -V nginx(RPM包校验),debsums nginx(Debian包校验)
原理:rpm -V对比RPM数据库记录的文件属性(权限、大小、MD5)与当前文件,输出S(大小变)、M(权限变)、5(MD5变)等标记。debsums同理。当怀疑被篡改,先rpm -Vf /usr/bin/nginx校验单个文件,再rpm -Va | grep '^..5'查所有MD5变更文件。避坑:rpm -V不校验配置文件(因配置文件允许修改),需单独md5sum /etc/nginx/nginx.conf。临时提权审计:
sudo -l查当前用户可执行的sudo命令,sudo -k清除凭证缓存
原理:sudo -l显示/etc/sudoers中为该用户授权的命令,避免盲目sudo su -。sudo -k强制下次sudo需重新输密码,防止凭证被恶意复用。实操心得:在共享服务器上,每次sudo操作后执行sudo -k,是基本安全习惯。
4. 实操全流程:一次完整的线上故障处理复盘
4.1 故障现象与初步响应
某日凌晨3:15,监控系统报警:公司官网首页HTTP状态码502错误率突增至80%,同时Nginx错误日志持续刷connect() failed (111: Connection refused) while connecting to upstream。我立刻登录跳板机,执行第一反应命令:systemctl is-active nginx确认Nginx主进程存活(返回active),排除服务崩溃。接着ss -tuln | grep :80验证80端口监听正常(输出LISTEN 0 128 *:80 *:*),说明Nginx网络层无异常。此时定位到问题在上游服务——即Nginx代理的后端应用。
4.2 上游服务深度诊断
根据Nginx配置,上游指向http://127.0.0.1:8080,于是执行:
# 查8080端口是否被监听 ss -tuln | grep :8080 # 若无输出,说明后端服务未启动 # 若有输出,查进程 lsof -i :8080 # 输出:java 12345 deploy 123u IPv6 1234567 0t0 TCP *:http-alt (LISTEN) # 确认是Java进程,PID 12345接着查该进程状态:ps -p 12345 -o pid,ppid,cmd,%mem,%cpu,etime,发现%mem高达95%,etime(运行秒数)仅120秒,说明进程刚启动不久。再查内存:cat /proc/12345/status | grep -E "VmRSS|Threads",VmRSS显示实际物理内存占用2.1GB,而容器内存限制为2GB——确认OOM被杀。验证:dmesg -T | grep -A 10 -B 10 "12345",日志明确显示“Out of memory: Kill process 12345 (java) score 892 or sacrifice child”。
4.3 根因分析与临时修复
OOM原因需查JVM参数:ps -p 12345 -o cmd=获取启动命令,发现-Xmx3g(最大堆3GB)但容器限制2GB,严重超配。临时修复分三步:
- 立即恢复服务:
systemctl restart app-backend重启服务,但需先调整JVM参数。编辑启动脚本,将-Xmx3g改为-Xmx1536m; - 释放内存压力:
echo 1 > /proc/sys/vm/drop_caches清页缓存(仅临时缓解); - 防止再次OOM:
systemctl set-property app-backend MemoryLimit=2G(systemd v240+支持)限制进程内存。
执行后,curl -I http://localhost:8080/health返回200,Nginx 502消失。
4.4 长期加固与自动化
- 配置JVM内存自动适配:在启动脚本中加入
# 获取容器内存限制 MEM_LIMIT=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null | awk '{printf "%.0f", $1/1024/1024}') # 设置JVM堆为限制的75% JAVA_OPTS="-Xms${MEM_LIMIT}m -Xmx$(($MEM_LIMIT*75/100))m" - 部署OOM监控脚本:
#!/bin/bash # 每5分钟检查dmesg是否有OOM if dmesg -T | tail -100 | grep -q "Out of memory"; then echo "$(date): OOM detected!" | mail -s "ALERT: OOM on $(hostname)" admin@example.com fi - 标准化部署流程:所有Java服务上线前,强制执行
systemctl show --property=MemoryLimit app-backend验证内存限制已设置。
5. 常见问题与独家排查技巧实录
5.1 “命令找不到”问题的五层排查法
当bash: rsync: command not found,别急着重装,按顺序检查:
- PATH路径:
echo $PATH确认/usr/bin等标准路径存在; - 命令是否存在:
which rsync或command -v rsync,若无输出,说明未安装; - 包管理器状态:
rpm -q rsync(CentOS)或dpkg -l | grep rsync(Ubuntu),确认包已安装; - 二进制文件权限:
ls -l $(which rsync),检查是否为-rwxr-xr-x,若无执行权限chmod +x $(which rsync); - 动态库依赖:
ldd $(which rsync),若提示not found,用yum install glibc补依赖。
提示:
command -v比which更可靠,因which可能被alias覆盖,而command绕过shell函数和alias。
5.2 “权限拒绝”的终极诊断清单
Permission denied错误常被误判为权限问题,实际可能有七种原因:
| 场景 | 诊断命令 | 解决方案 |
|---|---|---|
| 文件权限不足 | ls -l /path/to/file | chmod 644 /path/to/file |
| 目录执行权限缺失(影响cd) | ls -ld /path/to/dir | chmod +x /path/to/dir |
| SELinux阻止 | ausearch -m avc -ts recent | grep file | setsebool -P allow_something 1 |
| AppArmor限制(Ubuntu) | dmesg | grep apparmor | aa-status查状态,aa-disable /path/to/profile |
| 文件系统只读 | mount | grep " / " | mount -o remount,rw / |
| NFS挂载选项 | mount | grep nfs | 检查nfs挂载是否含ro选项 |
| 用户被禁止登录 | passwd -S username | passwd -u username解锁 |
注意:
ls -l显示的rwx是基础权限,但getfacl /path能查看ACL扩展权限,lsattr /path查看chattr隐藏属性(如i不可修改)。
5.3 日志分析的三个致命误区与修正
误区一:只看最新日志
tail -f /var/log/nginx/error.log可能错过历史线索。修正:用journalctl -u nginx --since "2023-01-01" --until "2023-01-02"查指定时段,或zcat /var/log/nginx/error.log.1.gz \| grep "502"查压缩日志。误区二:忽略日志级别
grep "error" /var/log/app.log会匹配warning和error,噪音大。修正:用awk '/\[ERROR\]/ {print}' /var/log/app.log精确匹配方括号内的ERROR。误区三:不关联多日志源
Web服务502错误,需同时查Nginx日志(客户端视角)、后端应用日志(服务端视角)、系统日志(/var/log/messages查OOM)。修正:用multitail -e "nginx" -e "app" -e "messages"并行查看三日志,用F键同步滚动。
5.4 性能瓶颈的“四象限”定位法
当CPU使用率100%,先用top看是用户态(us)还是系统态(sy)高:
- us高:应用代码问题,用
perf top查热点函数; - sy高:内核态开销大,用
pidstat -w 1查上下文切换,iostat -x 1查IO等待; - id低但wa高:IO瓶颈,
iotop看进程IO; - id低但si高:软中断过多,
sar -n DEV 1查网卡中断。
实操心得:
vmstat 1是入门首选,r(运行队列)> CPU核数说明CPU饱和,b(阻塞进程)>0说明IO等待,swpd>0说明内存不足触发swap。
6. 工具链整合:让100条命令真正“活”起来
6.1 自动化巡检脚本框架
把高频命令封装成每日巡检脚本,是运维专业性的体现。以下是一个精简版框架:
#!/bin/bash # daily_check.sh LOGFILE="/var/log/daily_check_$(date +%Y%m%d).log" echo "=== Daily Check $(date) ===" >> $LOGFILE # 磁盘检查 echo "--- Disk Usage ---" >> $LOGFILE df -h | grep -E "(^Filesystem|/dev/sd)" >> $LOGFILE if [ $(df -h | awk '$5+0 > 90 {print $1}' | wc -l) -gt 0 ]; then echo "ALERT: Disk >90%" >> $LOGFILE fi # 内存检查 echo "--- Memory ---" >> $LOGFILE free -h >> $LOGFILE if [ $(free | awk 'NR==2 {print $7/($3+$4)*100}' | cut -d. -f1) -gt 90 ]; then echo "ALERT: Available memory <10%" >> $LOGFILE fi # 服务状态 echo "--- Services ---" >> $LOGFILE systemctl list-units --state=failed --no-pager >> $LOGFILE # 发送报告 mail -s "Daily Check Report" admin@example.com < $LOGFILE关键设计:
awk 'NR==2 {print $7/($3+$4)*100}'计算可用内存百分比($7是available,$3+$4是total),避免free的used列误导;systemctl list-units --state=failed只查失败服务,比systemctl --failed更精准。
6.2 命令别名与函数的最佳实践
在~/.bashrc中定义别名,能极大提升效率,但需遵循安全原则:
- 安全别名:
alias ll='ls -alF --color=auto'(加--color增强可读性); - 防误操作别名:
alias rm='rm -i'(删除前确认),alias cp='cp -i'; - 功能增强别名:
alias grep='grep --color=always'; - 复杂操作函数:
# 快速查找并杀进程 killproc() { local proc_name=$1 if [ -z "$proc_name" ]; then echo "Usage: killproc <process_name>" return 1 fi local pids=$(pgrep -f "$proc_name") if [ -n "$pids" ]; then echo "Killing processes: $pids" kill -15 $pids sleep 2 kill -9 $pids 2>/dev/null else echo "No process found matching '$proc_name'" fi }
注意:别名不能替代脚本逻辑,复杂操作必须用函数;所有别名加
-i参数,避免误操作。
6.3 终端效率提升的五个冷技巧
- Ctrl+R反向搜索历史:按
Ctrl+R,输入关键词(如nginx),自动匹配最近执行的nginx相关命令,Ctrl+R继续上一条; - Ctrl+A/Ctrl+E跳首尾:
Ctrl+A光标移至行首,Ctrl+E移至行尾,比Home/End键更快; - **Alt+.
粘贴上条命令参数**:执行cp /long/path/to/file.txt /tmp/后,在新行按Alt+.,自动粘贴/tmp/`,省去重复输入; - !$引用上条命令末参数:
ls /var/log/nginx/后,cd !$直接进入该目录; - Ctrl+U/Ctrl+K删整行:
Ctrl+U删光标前所有字符,Ctrl+K删光标后所有字符,比Backspace/Delete高效得多。
实操心得:这些技巧看似微小,但每天节省的键盘敲击次数累积起来,一年能少按上万次键。
7. 最后的经验之谈:运维不是命令的堆砌,而是风险的预判
十年前我第一次独立处理生产事故,面对满屏的df -h输出,手心全是汗,生怕敲错一个字符就让服务雪上加霜。现在回头看,那些让我彻夜难眠的“技术难题”,90%源于对风险的无知——不知道rm -rf会跳过回收站,不清楚dd的of=写错设备名会直接覆写硬盘,不明白systemctl restart可能触发服务依赖的连锁重启。这份100条命令清单,我刻意没有按字母排序,而是按故障处理的思维流组织:从发现问题(磁盘、网络),到定位根因(进程、日志),再到修复与预防(安全、自动化)。它真正的价值,不在于让你记住每条命令的参数,而在于培养一种肌肉记忆:看到502,本能想到查上游端口和OOM;看到df告警,第一反应是df -i和lsof;看到权限错误,条件反射执行ausearch和getfacl。运维的本质,是把不确定性转化为确定性,把救火变成防火。当你不再问“这个命令怎么用”,而是思考“为什么这个命令能解决这个问题”,你就已经跨过了新手的门槛。最后分享一个小技巧:把这份清单打印出来,贴在显示器边框上,每次解决一个问题,就用荧光笔划掉对应命令——划掉的不是命令,是你亲手填平的一个认知鸿沟。