运维这行干久了,你会发现一个规律——真正拉开差距的不是你会不会部署某个服务、能不能写出漂亮的脚本,而是当你面对一台状况不明的服务器时,能不能用最基础的命令快速定位问题。我刚带团队那会儿,很多新人问我“系统管理命令”到底怎么学,我给的建议一直没变:先别急着背参数,把命令背后“系统是怎么运转的”这件事搞清楚。这篇博文就从我日常最常用、也最容易被低估的Linux系统管理命令说起,聊聊它们到底解决了什么问题、怎么用最稳、踩过哪些坑。
我自己工作这么多年,从单机部署到维护几十台Linux服务器的集群环境,每天离不开的就是进程怎么看、内存怎么查、磁盘怎么清、服务怎么管、日志怎么翻。这些操作全落在系统管理命令上。这篇文章不整那些花里胡哨的“高级技巧合集”,就挑生产环境中真正高频的命令,配合真实场景复盘,帮你把基础打扎实。无论是刚入门的新手,还是想沉淀一下细节的老手,应该都能从中拿走点东西。
1. 系统状态与进程管理:先会“看”,再谈“管”
1.1 用 top 和 ps 快速判断系统当前状态
我接手过很多“卡死了”的服务器,第一件事永远不是重启,而是先看当前系统到底卡在哪。top是首选,因为它的动态刷新相当于给系统做一个实时体检。
top界面第一行能看到当前时间和负载均值,三个数字分别代表1分钟、5分钟、15分钟的负载。判断标准很简单:如果负载值持续大于CPU核数,说明系统处于过载状态。举个例子,一台8核的机器,load average 如果长期在10以上,那基本可以断定CPU资源被某些进程吃满了。
按1键可以展开每个CPU核心的使用情况,这一步容易忽略但很有用。很多老手看top只盯着CPU那行平均值,其实单核跑满和多核均衡分布是完全不同的两类问题。前者往往是某个进程绑核或者中断分布不均,后者才是整体资源不足。
ps是个老牌命令,但它能发挥的作用远不止ps -ef看进程列表。我常用的几个组合:
# 查看某个进程的资源占用排行 ps aux --sort=-%cpu | head -n 15 # 查看某个服务进程是否存活 ps -ef | grep nginx | grep -v grep # 查看线程级别的CPU占用 ps -eLf | awk '{print $2, $3, $4, $6, $7}' | head这里有个细节:grep -v grep这个过滤一定要加,否则你看到的“进程”可能只是你自己的查询命令。这个坑我刚入门时踩过不止一次——查了半天发现服务是好的,只是grep匹配到了自己。
如果top里的某个进程CPU占用超过100%,说明它是多线程进程,并不是bug。判断时要结合%CPU和进程数看,别一看数值高就紧张。
1.2 内存管理与 free 的深度解读
内存问题比CPU问题更隐蔽。free -h这个命令大家都会敲,但很多人看不懂输出的含义,尤其分不清“free”和“available”的区别。
$ free -h total used free shared buff/cache available Mem: 31Gi 12Gi 1.2Gi 345Mi 18Gi 18Gi Swap: 0B 0B 0B关键看 available 这列,它才是系统真正还能分给新进程的内存。free 小不用慌,因为Linux会尽量把内存用来做文件缓存(buff/cache),这部分内存在有需要时可以释放给应用程序。你机器里明明写着只剩1.2G空闲,但跑新服务也没问题,就是因为buff/cache能顶上。
我们曾经遇到过一个诡异的内存问题:free 看着还有很多,但服务一启动就报内存不足。查了半天最后发现是ulimit -v(虚拟内存限制)被设死了。所以排查内存问题时,除了 free,还要看一眼进程的资源限制:
# 查当前shell的资源限制 ulimit -a # 查某个进程的资源限制 cat /proc/<PID>/limits这类问题在容器环境和CI构建机上特别常见,某些基础镜像默认就把进程数或者虚拟内存限制得很死,不查 limits 根本想不到。
还有一点,swap的使用要留意。如果 swap 长期占用很高且不断波动,内存多半吃紧了,加内存或者优化应用内存占用才是正路。盲目清 swap 只是掩耳盗铃,系统很快又会把数据换进去,反而白白增加IO开销。
1.3 综合劲组合:watch 和 uptime
watch是我非常爱用的一个命令,它的价值在于持续观察。比如你盯着free -h看内存变化,直接跑:
watch -n 1 free -h每秒刷新一次,内存是怎么涨上去的、有没有突然掉下来,全看得清清楚楚。排查内存泄漏时,我会同时开三个窗口:一个 watch free,一个 watch “ps aux --sort=-%mem | head”,一个看业务日志,逐个对照。
uptime本身信息量不大,但它输出里的 load average 配合watch就厉害了。我习惯在压测时跑watch -n 1 uptime,负载的涨落曲线比任何监控图都直观。
我个人的体会是,进程和内存管理是系统管理的第一层地基。千万别以为会ps -ef就算精通进程管理,能把 top 里的各项指标讲明白、能通过 free 判断内存水位的人,才算是真的入了门。
2. 用户、权限与文件系统管理:权限不清,后患无穷
2.1 用户和组的管理命令实操
用户管理最怕的不是不会敲命令,而是敲完之后权限乱套。先看基本操作,这是每个运维都必须背下来的内容:
# 创建用户并指定家目录和shell useradd -m -s /bin/bash deploy # 给用户添加密码 passwd deploy # 把用户加入附加组 usermod -aG docker deploy # 查看用户的组和uid/gid信息 id deploy这里必须强调-aG和-G的区别。-aG是追加附加组,-G是重新指定附加组列表。用后者的时候如果不带-a,会把用户原有的附加组全部覆盖掉。我见过因为这条命令把管理员误移出 sudo 组,导致后续所有操作都提不了权的案例。所以凡是涉及修改组成员关系,永远建议加上-a。
删除用户时同样要谨慎:
# 仅删除用户,保留家目录 userdel deploy # 删除用户并同时删除家目录和邮件池 userdel -r deploy如果是离职人员的账号,我一般不会直接删,而是先在 passwd 文件里把 shell 改成/usr/sbin/nologin,再锁定账号:
usermod -L deploy usermod -s /usr/sbin/nologin deploy这样做的好处是保留账号痕迹,审计时还能查到谁是谁,但已经无法登录系统。直接删除账号看似干净,后续审计日志一旦需要回溯,就什么都找不回来了。
组的操作相对简单,但有一个点容易忽略:用户新增到附加组之后,如果该用户当前已经登录,新的组权限要重新登录才生效,这个不是bug,是会话缓存机制。排查“明明加到组里了为什么还报权限不够”时,先让用户重新登录一次。
2.2 权限设置:不仅仅是 chmod 777
chmod 和 chown 是出场率最高的两个命令,同时也是被滥用最严重的。
很多人图省事直接chmod 777,这我强烈反对。777意味着任何用户都能读写执行,一旦服务器上有其他可写目录,配合web服务很容易演变成恶意文件上传的入口。我处理过的入侵事件里,相当一部分根因就是某个目录被粗暴地设置成了777。
更合理的做法是精确控制:
# 目录设置775,文件设置664,属主和属组分别指定 chown -R appuser:appgroup /data/www chmod 755 /data/www find /data/www -type f -exec chmod 644 {} \;用 find 批量修正文件权限是生产环境的高频操作。目录保留执行权限用于进入,文件剥离执行权限避免脚本误执行。
另外要熟悉特殊权限位,比如 setuid。:wq剩下来再没有。setuid 可以理解为给某个可执行文件设置了一个“临时身份提升”,比如/usr/bin/passwd就有 setuid 权限,普通用户运行它时以root身份改自己的密码。在日常管理中,配置 sudo 比到处设置 setum 安全得多。检查系统里哪些文件带有特殊权限位,非常建议大家定期执行:
# 查找所有具有setuid权限的文件 find / -perm -4000 -type f 2>/dev/null凡是出现在这个清单里的,都应该逐个确认合理性。我处理过的挖矿病毒有一个典型动作就是给常用命令加上setuid后门,这类后门很难发现,但定期扫一遍还是能抓到。
2.3 磁盘占用与 inode 耗尽排查法
磁盘满这个话题可以写一部血泪史。最常见的情况是df -h看容量还剩20%,但程序一直报“No space left on device”。这时候十有八九是inode耗尽了。
# 查磁盘容量使用率 df -h # 查inode使用率 df -i小文件过多是inode耗尽的元凶。比如临时目录下堆积的session文件、日志切割后残留的小文件。清理时别只盯着大文件看,用下面的命令快速找出哪个目录文件数最多:
# 统计当前目录下各子目录的文件数 for d in */; do echo "$d : $(find "$d" -type f | wc -l)"; done如果文件真的多到rm都受不了,可以考虑先隐藏目录再后台慢慢删,避免删除过程中业务还在往目录里写文件,边删边写会让清理时间无限拉长。
du这个命令也要会用,只看df不看du等于只看到结果不知道原因:
# 查看当前目录下各子目录占用大小 du -sh * | sort -rh | head -n 10sort -rh 是按人类可读的大小反向排序,一眼就能看出哪个目录是空间大户。每次磁盘告警,我都是先用这招定位,再决定怎么清理,绝不盲目找大文件乱删一通。
3. 服务管理与日志排查:从启动到故障的完整链路
3.1 systemctl 管理的核心思路
现在主流的Linux发行版基本都是systemd管理服务,systemctl成了服务管理的核心命令。但很多人只会那几个固定搭配——start、stop、restart、status,遇到问题就抓瞎。
我整理一个生产环境最常用的systemctl清单:
# 查看服务状态,带详细日志输出 systemctl status nginx # 设置开机自启 systemctl enable nginx systemctl disable nginx # 查看服务依赖项 systemctl list-dependencies nginx # 重新加载某个服务的配置 systemctl reload nginx # 查看所有失败单元 systemctl --failed这里有个关键区别:restart是彻底停掉再启,reload是让进程重新加载配置而不中断连接。Nginx、Nginx 改动配置时用 reload 是平滑的,不会打断正在进行的请求。数据库这类服务更明显,你用 restart 会闪断,改成 reload 或者发特定的信号才能做到热更新。
systemctl status nginx不是只显示服务状态,它最下面的日志片段才是排障入口。如果服务起不来,看这里基本能确定是配置语法问题还是端口冲突。真正排查问题往外挖的时候,系统日志里一般也能看到线索。
还有一个大家容易忽略的用法:
# 查看某服务的完整进程树 systemctl status nginx --no-pager # 实时跟踪某服务的标准输出 journalctl -u nginx -f-u指定unit名,搭配-f实现实时跟踪,效果和 tail -f 类似,但直接和systemd日志联动,比翻log文件更省事。
3.2 journalctl 日志查询的正确打开姿势
如果说 systemctl 是服务的开关,那journalctl就是服务的“黑匣子”。日志查询不熟练,等于盲人摸象。
几个高频使用场景我列一下:
# 查看上一次启动后的所有日志 journalctl -b # 查看指定时间段的日志 journalctl --since "2024-01-01 10:00:00" --until "2024-01-01 12:00:00" # 查看某个服务最近100行 journalctl -u nginx -n 100 # 查看特定进程的日志 journalctl _PID=12345生产环境排查故障,最关键的就是按时间窗口过滤。有一次线上告警发生在凌晨两点,我直接用--since和--until把日志缩小到两分钟窗口内,马上定位到某条定时任务执行超时导致服务异常。如果不加时间过滤,在几十万行日志里翻找等同于大海捞针。
还有一个技巧是通过日志竖直上翻查出告警之前的征兆。journalctl 默认用less分页,退出之后日志会停在末尾,按Shift+g跳到结尾再按PageUp往上翻,告警前几秒发生了什么,尽收眼底。
如果日志量过大导致 journalctl 查询很慢,建议维护时清理一段时间之前的日志,或者调大journal最大占用空间。很多人把journal的磁盘占用设置成默认值,结果日志目录把磁盘塞满,这属于是日志服务把自己搞挂了,挺冤枉的。
3.3 定时任务的排查与坑
服务管理还绕不开 crontab,很多系统问题都源于“定时任务没跑”或者“定时任务跑重复了”。
# 查看当前用户的定时任务 crontab -l # 编辑当前用户的定时任务 crontab -e # 查看某个用户的定时任务(root) crontab -u nginx -l定时任务不执行,先查三处:一是crond服务本身是否在跑,二是脚本是否有执行权限,三是脚本里的路径是否是绝对路径。第三点是最常见的坑,cron的环境变量和SSH登录环境不一样,PATH可能短得可怜,脚本里直接写python3可能在终端能跑,在cron里就找不到命令。解决方法是脚本开头写全路径或者 source 一段基础环境变量。
排查定时任务到底有没有触发,最直观的方法是看日志:
# 查看crond服务日志 grep CRON /var/log/syslog # 或通过journalctl journalctl -u crond -fcrontab -e编辑时代码写错导致语法有问题,crond 会拒绝加载整个文件,这是很坑的。所以在改完定时任务后,建议立刻crontab -l确认内容正常,也建议在脚本里加上执行结果的日志重定向:
*/5 * * * * /usr/local/bin/check_health.sh >> /var/log/check_health.log 2>&1日志输出是排查定时任务问题的重要参考,没有重定向就等于事后完全无法查看执行情况。
4. 网络与性能排查的常用命令组合
4.1 网络连通性排查四板斧
网络问题占日常故障的比例非常高。排查顺序我总结为四板斧:ping、ss、traceroute、curl。
先ping确认基本连通性,再ss看端口监听状态。注意现在的系统里netstat已经不再是默认安装,官方推荐用ss,性能更好输出也清晰:
# 查看某个端口是否在监听 ss -lntup | grep 8080 # 查看所有TCP连接及状态 ss -ant # 查看与某个服务相关的连接统计 ss -sss -lntup里的-l是listening、-n不做域名解析、-t只看TCP、-u看UDP、-p显示进程名。这个命令能一次性告诉你端口谁占着、监听在哪个地址、对应哪个进程。排查端口冲突时靠它一条命令就能定案。
端口在监听但业务仍然访问失败,下一步就要看防火墙和路由了。服务器上查防火墙的常用命令:
# firewalld firewall-cmd --list-all # ufw ufw status verbose # iptables iptables -L -n --line-numbers很多开发环境部署好了服务但外部访问不通,80%的闹剧都出在防火墙规则或者服务只监听了127.0.0.1。检查时一定要看监听地址:如果显示127.0.0.1:8080,说明服务只能本机访问,外部根本连不上。正确的局域网访问姿势是监听0.0.0.0:8080或具体网卡IP。
再往下就是路由和链路问题,用traceroute判断数据包在哪一跳丢失,以及用curl -v观察HTTP层面的握手响应:
# 查看HTTP请求的全过程细节 curl -v http://127.0.0.1:8080/health # 限制超时时间,避免线程卡死 curl -m 5 http://127.0.0.1:8080/curl -v输出里能明确看到TCP连接级别和TLS握手级别进展,属于网络排查的“分层定位”。
4.2 性能瓶颈定位:vmstat、iostat 和 sar
系统卡顿不一定都是CPU的问题,还可能是磁盘IO慢、内存不够导致的swap颠簸。我压测时习惯用vmstat做第一梯队的性能扫描:
vmstat 2 10每两秒刷新一次,一共输出10次。看几列就行:r是运行队列长度,大于CPU核数就是过载;si和so是swap换入换出,长期不为0说明内存不足;wa是IO等待占比,持续偏高意味着磁盘是瓶颈。
磁盘IO的详细情况用iostat看:
iostat -x 2 3重点看%util和await。%util接近100%说明磁盘几乎满负荷运转,await高说明每次IO请求都要排很长时间队。这套数据判断数据库机器磁盘是否抗压非常有效。
如果要看历史趋势,还得用sar,它是系统活动记录器,很多系统自带但需要安装sysstat包:
# 查看今天的历史CPU负载 sar -u # 查看历史内存使用 sar -r # 查看历史磁盘负载 sar -dsar的价值在于事后复盘,比如你可以回看昨天下午三点CPU是不是异常飙升。实时监控能看到当下的病,sar能看到老黄历上的病因。
4.3 港口与连接数的查看技巧
这个小节补充一个容易被忽略的数字:文件描述符限制。
高并发服务最常遇到的问题不是CPU不够,而是连接数太多导致文件描述符耗尽。ss看连接数,但很多部署环境的连接数和最大文件数对不上:
# 查看当前进程打开的文件数 ls /proc/<PID>/fd | wc -l # 查看进程的limit限制 cat /proc/<PID>/limits | grep "open files"如果连接的复用策略配置得不好,当前连接数很容易逼近甚至打满open files限制。调优时要同时看系统级和用户级的ulimit -n:
ulimit -n修改通常要动/etc/security/limits.conf,再配合systemd服务里的LimitNOFILE参数一起改。只改一边的坑我也踩过,明明limits.conf调大了,systemd跑的服务还是受限,因为systemd自己会覆盖这部分配置。
5. 常用排查套路与事后复盘
5.1 我调试故障的通用排查流程
说了这么多命令,最后整理一下我在生产环境排查故障时习惯走的流程。这套流程不金贵,但很实用,适合参考:
- 先看全局状态:
uptime+top,判断是CPU、内存还是负载问题。 - 再看磁盘水位:
df -h+df -i,排除空间和inode耗尽。 - 确认关键进程:
ps -ef+systemctl status,排除进程假死或服务未启动。 - 查日志定位根因:
journalctl -u 服务名 -n 100 --since "时间点",找到报错上下文。 - 网络链路验证:
ss -lntup看端口,curl -v验证本机和外部访问视角的差异。 - 处理并记录:恢复后用
sar回顾历史数据,把排查过程和结论写进事后记录。
这套流程基本能覆盖我日常工作里70%的问题。剩下的30%虽然各不相同,但前几步的排查信息越准确,定位速度就越快。
在我实际工作中,这个过程还会配合一个单独的终端保存现场数据,比如把top -bn1和ss -ant的输出重定向到文件,为事后查阅留档。这个习惯让我在复盘复杂故障时省了很多力气,建议大家也这么做。
5.2 复盘:哪条命令帮我解决过最棘手的故障
回看这些年,ss帮我解决过最棘手的问题。有一次数据库连接池频繁告警,业务方一口咬定是数据库机器负载问题,我登录服务器top一看负载确实高,但进一步用ss -s观察连接数,发现TIME_WAIT状态连接数量异常爆炸,问题其实是客户端没走连接复用导致频繁创建短连接。
和业务方对照之后,优化了连接池配置,负载马上降下来。如果只看top,一定会走弯路去调数据库参数,说不定还把问题整得更乱。
所以我对系统管理命令的态度是:命令本身不难,难得是通过命令组合出完整的系统视角。单独一条命令只是工具的点击,多条命令交叉验证、配合业务状态共同判断,才算真的“会管理”Linux系统。
最后再多说一句,我在实际排查中还养成了一个习惯:不管多紧急的故障,恢复之后一定花五分钟把命令输出、时间点、结论记下来。时间久了,这些记录就是最宝贵的经验库。没有这些复盘资料,很多坑遇到过就忘了,下次还得从头踩一遍。