☰
Linux常用命令实战:从权限到容器的排查思路
2026/10/3 14:15:55 网站建设 项目流程

这一篇是Linux常用命令系列的第六篇。写下这个标题的时候,我突然意识到这个系列已经被办公室同事当成了一本“应急小册子”在用。前几篇我们聊过文件、文本处理和基础网络,这一篇我想换个角度,不按命令字典的路子来,而是按“问题现场”来讲:你在排查用户权限、进程状态、日志异常、存储挂载和容器工具时,究竟应该敲哪些命令,为什么要敲这些命令,踩过坑之后还能怎么补救。这个定位更适合两类人:一是刚转运维或开发,需要快速建立一套排查思路的同学;二是被生产环境反复折腾过,但缺少系统整理的老手。命令这东西,背是背不完的,真正值钱的是你脑子里那条“先看什么、再看什么、最后怎么办”的链路。

1. 用户与会话:别等权限出问题再回头补课

1.1 新建用户的三个细节:家目录、Shell和sudo

新手最典型的一个坑就是用useradd建完用户,切过去发现连家目录都没有。原因很简单:CentOS/RHEL 系的useradd默认不会创建家目录,除非你显式加了-m。正确的姿势大概是这样的:

sudo useradd -m -d /home/zhang -s /bin/bash zhang sudo passwd zhang sudo usermod -aG sudo zhang

这里每个参数都不是摆设。-d指定家目录路径,如果你不写,默认会按/home/用户名来;-s指定登录 Shell,系统默认可能是 sh,进去以后方向键、补齐和历史记录都别扭,所以除非有特殊需求,我统一用/bin/bash。-m的意思是同时创建家目录,并且把/etc/skel里的模板文件复制进去,像.bashrc、.profile这些初始配置都是这么来的。

再强调一个容易忽略的细节:useradd -D可以查看当前系统创建用户的默认值,包括默认 Shell、家目录基准路径、默认用户组策略。批量上线账号前,先执行一下这条命令,能提前发现“为什么所有人建出来都是 nologin Shell”之类的幺蛾子。

sudo 授权也有讲究。Debian/Ubuntu 系的发行版通常用sudo这个用户组,而 CentOS 系用的是wheel。最常见的问题是:明明把用户加进了组,却依然无法 sudo,很可能是改错了组名,或者用了usermod -G而不是usermod -aG。-G会直接覆盖用户的附加组列表,不加-a,等于把用户之前加入的所有补充组全部清空,轻则权限缺失,重则连 docker 组、dev 组都没了。所以我的习惯是:凡是追加组,永远写全-aG。

另外一个安全习惯是不要直接用vim /etc/sudoers去改文件,除非你想被语法错误锁死。正确操作是visudo,它会在保存前做语法检查。如果你要给某个用户特别权限,建议在/etc/sudoers.d/下建一个独立文件,比如:

echo "zhang ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx" | sudo tee /etc/sudoers.d/zhang-nginx sudo visudo -c

生产环境尽量别用NOPASSWD: ALL,那样和把一个 root 口令贴在工位上没什么区别。

1.2 停用、锁定和删除:删用户不是按个回车

删除用户最干净的方式是userdel -r,-r会连家目录和邮件池一起删。但在生产环境里我吃过一次亏:有一个服务用 systemd 的User=daemon跑着,我直接删了那个用户,结果一堆文件变成了数字 UID 所有,排查了半天才反应过来。所以删除之前,先查一下这个用户是否还有进程在跑:

ps -u olduser -o pid,cmd pkill -u olduser

如果确认要删,还建议先把家目录打个包再执行删除,万一里面有配置文件和脚本,后悔药还有得吃。另外,运维审计要求不能删账户而必须锁账户时,可以用:

sudo passwd -l olduser sudo usermod -L olduser

两条命令都能让账户无法登录,但侧重点略有不同。passwd -l是给密码字段加锁,而usermod -L是直接锁定用户。真正常被忽略的是,这两个操作都只影响后续登录,已经建立的会话不会马上被踢掉。如果你需要立刻踢人,还得配合pkill -u olduser或loginctl terminate-user olduser。

顺带说一句lastlog和last:前者能看每个用户最后登录时间,后者看登录历史记录,包括重启时间点。排查“谁半夜动过服务器”基本都是靠这两个命令起手。

1.3 会话和后台运行:别再用 nohup 硬扛了

看当前系统上有谁在线,我一般用w,它能显示登录用户、终端、来源 IP、当前在跑什么命令,比单纯的who信息全。需要看历史登录记录用last,需要看失败登录记录要用lastb,这个命令需要 root 权限。

后台运行工具这块,很多人一说就是nohup command &。说实话,nohup 能解决“终端关闭后进程不退出”的问题,但它解决不了“会话丢了就找不回来”的问题。如果任务是编译、数据同步、压测这种需要持续盯着的活,我更推荐tmux:

tmux new -s task # 跑你的命令,然后 Ctrl+B 再按 D 脱离会话 tmux attach -t task

为什么推荐它?因为 tmux 把会话和服务端绑在一起,就算你 SSH 断开、本机网络抖动,会话里的进程也不会被 SIGHUP 带走,下次连上去直接tmux attach就能接着看。nohup 能做的它都能做,还能多窗口、分屏、日志回看。如果是临时起一个进程,也可以考虑setsid command,它会创建新的会话并脱离终端控制,但操作体验和回看能力都不如 tmux。我的建议是:一次性任务用 nohup,需要长期跟踪的任务一律 tmux。

1.4 口令策略和过期提醒

密码过期这事其实挺容易踩坑。你以为设置了过期时间,系统就会在用户登录时提醒,但实际上,很多环境里用户根本收不到提示,因为他们用的密钥登录,根本不会走到密码验证那一步。常见操作是把这三条配合起来:

sudo chage -M 90 zhang # 密码最长使用 90 天 sudo chage -W 7 zhang # 过期前 7 天开始警告 sudo chage -d 0 zhang # 强制下次登录改密码

查看用户当前密码有效期用chage -l zhang,清理临时账号也可以用chage -E 2025-12-31 zhang给它加一个失效日期。我自己写巡检脚本时,会给所有用户循环执行chage -l,再配合lastlog输出,基本能覆盖大多数账户合规需求。

2. 进程与资源:用命令拼凑一张“现场图”

2.1 别把 ps 当“拍一下照片”

ps是最常用的进程查看命令,但很多人只会ps -ef然后瞪眼找。我先说两个固定的看点:ps -ef输出里,PPID是指父进程 ID,C是 CPU 使用率;ps aux输出里,%CPU、%MEM、VSZ、RSS这些字段非常直白,RSS 是物理内存占用,VSZ 是虚拟内存。排查内存泄漏时,我会先用ps aux --sort=-%mem | head把内存占用 Top10 拎出来。

再一个是过滤技巧。直接ps -ef | grep nginx经常会带出那条 grep 自身的进程,很碍眼。更稳的办法是用pgrep:

pgrep -f "nginx: worker"

-f表示匹配完整命令行,而不仅仅是进程名。这在过滤脚本类进程时尤其有用,比如pgrep -f "python.*app.py"。但注意,-f匹配的是整个命令行,如果命令行里包含特殊字符且不带引号,容易把自己 bash 的历史命令也匹配出来,所以使用前最好先用ps -eo pid,cmd | grep ...验证一下。

2.2 top 的批处理模式和 load average 怎么读

交互式top我基本只在临时看两眼的时候用,真正写进脚本和排查记录里的是批处理模式:

top -bn1 -o %MEM | head -20

-b是批处理,不刷屏,-n1只采样一次,-o %MEM按内存排序,等价于交互界面按大写 M。按 CPU 排序用-o %CPU,只看某个进程用top -p PID,只看指定用户用top -u zhang。

很多人对 load average 的理解是有偏差的。load average: 5.8, 3.2, 2.0分别表示 1 分钟、5 分钟、15 分钟的平均活跃进程数。但如果机器是 8 核,5.8 并不算高,反而说明有约 2 个核的空闲;如果是 4 核,5.8 就已经超载了。更重要的是,load 高不一定代表 CPU 忙,还有可能是大量进程进入了不可中断的D状态,比如 NFS 挂载失联、磁盘 IO 卡死。这时候 CPU 使用率可能很低,但系统已经处于半瘫痪状态。所以看到 load 高,先top看一眼排前面的进程状态是 R 还是 D,再往下查。

2.3 进程启动时间和“进程名对不上号”的问题

排查“这个服务到底什么时候被重启过”,最直接的是这条:

ps -p PID -o pid,lstart,etime,user,cmd

lstart是进程启动的绝对时间,etime是已经运行了多久。配合最近的上线记录或定时任务日志,基本就能对上号。

但这里有个高级一点的坑:Linux 进程名是可以被修改的。服务本身可以通过prctl(PR_SET_NAME)改自己的 comm 字段,启动脚本也可以用exec -a custom_name ./your_binary把 ps 显示的名字改成别的。所以常在 ps 里看到一个进程叫myserver,但它实际跑的是一个叫backup_agent.so的动态库程序。识别真实程序的办法很简单:

readlink -f /proc/PID/exe

这条命令能告诉你这个进程真正执行的二进制文件路径,比看 ps 输出靠谱得多。排查可疑进程时,/proc/PID/exe、/proc/PID/cwd、/proc/PID/environ这三个文件是必看的。

2.4 僵尸进程:kill -9 治不了的病

僵尸进程的标志是在ps输出里状态那列显示Z,命令行最后带着defunct。它的本质是子进程已经退出,但父进程没有调用 wait 回收它的退出状态。所以kill -9对僵尸进程完全无效——它不是活着的进程,你杀不掉一个已经死了的进程。

定位僵尸进程可以这样:

ps -A -o stat,ppid,pid,cmd | awk '$1 ~ /^Z/'

拿到 PPID 后,往上看这个父进程是什么,父进程如果没有异常就让它自己回收,如果父进程卡住了,通常要重启或干掉父进程,让僵尸变成孤儿被 init 收养,再由 init 统一回收。生产环境里我见过大量僵尸集中在某个宿主机,底层原因多半是容器里的 PID 1 进程没有正确处理子进程退出信号,或者 Java 程序的父进程没有 wait。这种问题在容器监控里非常典型,需要应用层面配合处理,而不是在操作系统层面硬杀。

2.5 资源限制:连接数上不去,先查 ulimit

高并发场景下最常见的报错是 Too many open files。这跟文件描述符(fd)上限有关,默认值在多数系统上是 1024,对 web 服务来说远远不够。查看当前限制和给指定进程设置限制的方法:

ulimit -n ulimit -n 65535

永久修改通常写在/etc/security/limits.conf或/etc/security/limits.d/下:

* soft nofile 65535 * hard nofile 65535

不过要注意区分 soft 和 hard:soft 是当前会话可以自行提升到的上限,hard 是硬性天花板。修改后必须重新登录或重启服务才生效,这也解释了为什么很多同事改了 limits.conf 以后,跑起来的进程仍然报 1024。验证进程实际生效值可以查:

cat /proc/PID/limits

排查 fd 占用数量用:

lsof -p PID | wc -l

如果这个数字持续上涨且不回落,基本可以断定是哪里连接没有释放,顺着 lsof 的输出继续查 FD 类型就行。

3. 日志检索:把 tail、grep、awk 串成一条流水线

3.1 grep 的正确姿势:上下文、边界和二进制

从日志里捞有效信息,第一反应是 grep,但很多人只会grep error app.log。我要补几个常用姿势:

grep -E "ERROR|timeout|deadlock" app.log | head -50 grep "ProductAPI" access.log -A 2 -B 2 grep -w "404" access.log

-A 2 -B 2是显示匹配行的前后 2 行,这个在查堆栈和异常上下文时简直是救命稻草。-w是单词边界匹配,避免你把404和4040混在一起。-E是多条件或正则匹配,比写好几个管道再合并干净得多。

还有一个非常烦人的问题是二进制文件。日志文件里混进了少量 \0 字节,grep 就会输出Binary file app.log matches,结果什么都看不到。解决办法是加-a或--text,强制按文本处理。递归搜索日志目录时,我建议直接用:

grep -rn --include="*.log" "ERROR" /var/log/app/

3.2 按时间段抽取:sed 和 awk 的分工

日志定位最常遇到的问题就是“这五分钟之内到底发生了什么”。如果日志格式整齐,每行开头是2025-02-01 12:30:00,可以用 sed 按行范围切:

sed -n '/^2025-02-01 12:30:00/,/^2025-02-01 12:35:00/p' app.log

但 sed 有个前提,就是日志本身是按时间顺序排的。如果日志文件被多线程写、被切割合并过,顺序乱了,sed 这套就不靠谱了。更通用的做法是用 awk 对字段进行比较:

awk '/^2025-02-01/ && $2 >= "12:30:00" && $2 <= "12:35:00"' app.log

这里假设$1是日期、$2是时间,字段分隔符是空格。如果日期格式不是标准开头,可以先用 grep 粗筛,再用 awk 精切。我处理 10GB 大日志时,经常是先grep "2025-02-01" big.log > day.log,把文件拉到 GB 级别以内,后面 sed 和 awk 的速度才会理想。

3.3 统计与去重:sort + uniq 才是完整搭档

想分析访问日志里哪些 IP 最活跃,最简单的流水线是:

cut -d' ' -f1 access.log | sort | uniq -c | sort -rn | head -10

这段命令的意思是:用 cut 切出 IP 列,sort 排序让相同 IP 挨在一起,uniq -c 统计次数,再按次数倒序取前 10。很多人只用uniq就发现统计不对,那是因为 uniq 只会合并相邻的重复行,不先 sort 的话,相同 IP 分散在文件各处根本合并不到一起。

统计 HTTP 状态码分布同理:

awk '{print $9}' access.log | sort | uniq -c | sort -rn

如果是四段式 nginx 日志,状态码字段在第 9 列,如果是其他格式可以先head -1 access.log确认字段位置。这套组合我每天都在用,跑完一眼就能看出 5xx 是否激增。

3.4 实时追踪:tail -F 和 tail -f 不是一回事

看日志实时输出用tail -f没错,但生产环境里日志经常按天轮转,比如 nginx 的 access.log 会被 rename 成 access.log.20250201,再新建一个 access.log。这时候你原来的tail -f还在盯着旧文件的 fd,新日志进来你完全看不见。正确做法是:

tail -F /var/log/app/app.log

大写 F 会按文件名追踪,文件被轮转后会重新打开新文件。这个坑我踩过不止一次,排查了半小时才发现日志一直没滚动,问题不在程序,而在 tail 的参数。配合管道过滤可以这样:

tail -F app.log | grep --line-buffered "ERROR"

如果用的是 systemd 管理的服务,直接看 journal 更省事:

journalctl -u my-service -f --since "1 hour ago" journalctl -u my-service --since "2025-02-01 12:30:00" --until "2025-02-01 12:35:00"

3.5 大日志文件别用 cat,less 才是阅读利器

我总是跟新人说,看到一个 5GB 的日志,千万别cat。正确工具是less:

  • less app.log打开后按/ERROR搜索,n跳下一处,N跳上一处;
  • 按G跳到文件尾,按g跳到文件头,按F进入类似于 tail -f 的跟随模式,Ctrl+C 中断跟随;
  • 直接读压缩日志:less app.log.gz,甚至zcat app.log.gz | head -50。

从这里你会发现,一段好的排查思路,其实就是 tail、grep、awk、sed、less 这几个命令的组合,单拎出来都简单,但组合起来能解决绝大多数日志问题。

4. 网络与存储:从连通性到挂载的排查套路

4.1 端口与服务:用 ss 替代 netstat

排查“端口明明在监听,为什么从外面连不上”,我有一套固定顺序。先看端口是否在本地监听:

ss -tulnp | grep 8080

-t看 TCP,-u看 UDP,-l只看监听,-n不做域名反解,-p显示进程信息,避免用 netstat 还要等半天反向解析。接着看有没有进程占着端口:

lsof -i :8080

如果监听正常,再去验证对方能不能通:

nc -vz 192.168.1.10 8080

-v显示详细过程,-z表示只扫描端口不发送数据。如果 IP 能 ping 通但端口不通,基本就是防火墙拦截,检查顺序是firewall-cmd --list-all或iptables -L -n -v。这里我要提醒一点:很多云主机的安全组规则是云平台层面控制的,操作系统里 iptables 是空的,那问题十有八九出在安全组,别再反复重启服务了。

处理建连数异常,可以用 ss 统计:

ss -ant state established '( dport = :443 )' | wc -l

看 TIME_WAIT 状态的连接数量,能帮你判断端口耗尽类问题。

4.2 DNS 排查:别忽略 systemd-resolved

解析出问题时的排查路径一般是:先手动解析目标域名,再检查系统接入的 DNS 配置。手动解析用 dig:

dig +short www.example.com

+short只输出 IP,非常干净。nslookup 也可以,但输出冗余,我日常用 dig 更多。然后看/etc/resolv.conf,确认 nameserver 指向哪里。如果你用的 Ubuntu 18.04 以上版本,这个文件很可能是被 systemd-resolved 管理的,手动改了以后重启网络又会被覆盖。查看实际生效的 DNS 状态:

resolvectl status

清 DNS 缓存用:

resolvectl flush-caches

很多“域名突然解析失败”的假故障,其实是缓存了过期的 A 记录,清一次缓存就好了。

4.3 NFS 和 CIFS 挂载:挂在墙上的不是命令,是坑

挂载 NAS 存储,NFS 最常见的挂载格式:

sudo mount -t nfs4 -o rw,bg,hard,intr,noatime 192.168.10.5:/data /mnt/data

bg表示后台重试,挂载失败时不会一直卡住终端;hard是硬挂载,intr允许中断,这两个配合起来能让进程在 NFS 失联时可被 Ctrl+C 打断。如果你用的是软挂载soft,NFS 服务抖动时会直接给应用返回 IO 错误,数据库之类的在线服务很容易写坏文件,所以生产场景我一般倾向 hard。但是 hard 挂载最大的副作用是:NFS 服务彻底失联时,ls那个目录会一直卡住,整个进程进入 D 状态,连 kill -9 都没反应。所以重要目录的 fstab 条目一定要考虑是否加nofail。

Windows/CIFS 共享挂载是另一套参数:

sudo mount -t cifs //192.168.10.20/share /mnt/share -o username=backup,password=xxx,vers=3.0,sec=ntlmssp

这里指定vers=3.0是防止老版本协议协商失败或安全性过差。挂在/etc/fstab时,有一个容易被忽略的选项是_netdev,它告诉系统“这是网络设备,等网络就绪后再挂载”,不加它,开机容易因为网卡没起来而挂载失败,严重时会卡在启动流程。一个参考条目:

192.168.10.5:/data /mnt/data nfs4 defaults,_netdev,nofail,noatime,hard,intr 0 0

写完之后先sudo mount -a验证语法,再用findmnt --verify检查 fstab 内容。NFS 挂载信息查看:

nfsstat -m

卸载不掉的挂载点用:

sudo umount -l /mnt/data

-l是 lazy 卸载,先把挂载点从目录树中摘除,等 IO 结束后再真正收尾。这种操作适合 NFS server 已经失联的紧急情况。

4.4 磁盘和 inode:df、du 之外还要会看 lsof

磁盘排查最基础的是df -h和du -sh。但如果你发现df -h显示分区已满,du -sh在对应目录统计出来的总量却对不上,优先怀疑一件事:有文件被进程删除但还没释放。Linux 下删掉的 open file 不会立刻释放空间,只有进程关闭 fd 才能释放。查找这种“隐形大文件”:

lsof +L1

+L1表示列出 link count 为 0 的被删文件,看到 PID 和进程名后,重启对应进程即可释放空间。

inode 耗尽也是一种满,表现是df -h还有空间,但无法创建文件。用df -i查看 inode 使用率。如果确实被大量小文件塞满,可以用:

find /data -xdev -type f -size +1G -exec ls -lh {} \; 2>/dev/null

-xdev限定不跨文件系统,避免扫到挂载点深处把结果搞混。找大文件和清 inode 是两个完全不同的思路,别混在一起。

5. 绕不开的工具命令:Docker、Redis、HDFS、GDB、ADB

5.1 Docker:日志、进容器、看资源占用

容器环境下的常用命令已经变成了日常的一部分。我写几个最常用的:

docker ps -a docker logs -f --tail=200 my-container docker exec -it my-container bash docker stats --no-stream docker inspect -f '{{.NetworkSettings.IPAddress}}' my-container docker top my-container

docker logs --tail=200避免直接把几千行日志打到终端;docker inspect后面那串 Go 模板语法看着唬人,实际上就是在取容器 IP;docker top能看到容器内进程在宿主机上的真实 PID,排查资源问题时常需要它。不要用docker attach,它和容器的主进程共享 stdin/stdout,用的时候一按 Ctrl+C 很容易把容器也停掉。理由很简单:attach是直接连主进程,exec是开一个新的交互进程,后者安全得多。

5.2 Redis:宁可慢,也不要用 KEYS

排查 Redis 问题,先redis-cli ping确认还活着,然后这几个命令轮流上:

redis-cli INFO memory redis-cli INFO stats redis-cli --scan --pattern "cache:*" | head -20 redis-cli SLOWLOG GET 10 redis-cli DBSIZE redis-cli TYPE user:10086

INFO系列是诊断一切的入口,内存、客户端连接数、命中率都在这。需要匹配大量 key 时,用--scan --pattern,千万不要用KEYS "*",因为 KEYS 会阻塞整个 Redis 实例,在生产环境上等于自杀。慢查询日志SLOWLOG GET能看到耗时过久的命令,再配合客户端 IP 去定位调用方,是排查 Redis 性能问题最常见的一条线。

5.3 HDFS:大数据同学的大文件操作

HDFS 和本地文件系统的命令风格很像,但细节不同:

hdfs dfs -ls -R /data hdfs dfs -mkdir -p /user/zhang hdfs dfs -put local_file /user/zhang/ hdfs dfs -get /user/zhang/remote_file ./local_file hdfs dfs -du -h /user/zhang hdfs dfs -rm -r /user/zhang/tmp_dir hdfs dfs -tail /user/zhang/log.txt

-du -h可以快速看目录下每个子目录的空间占用,排查“哪个目录把磁盘吃完了”很好用。HDFS 对小文件非常不友好,NameNode 会把每个文件、目录和 block 的元数据都放在内存里,上百万个小文件直接能把内存吃光。所以新人在做数据采集时,我建议先考虑合并写入,而不是堆零散文件。如果已经积累了一批小文件,可以用hdfs dfs -getmerge到本地再传回去,或者在调度层用 coalesce 处理。

5.4 GDB:调试崩溃程序的最后手段

GDB 看起来是 C/C++ 开发者的工具,但运维在排查 core dump 时也离不开。最基本的流程:

gdb ./your_program core.12345 (gdb) bt (gdb) info registers (gdb) info threads (gdb) thread 2

bt打印调用栈,崩溃现场第一件事就是bt;info registers看寄存器值,配合反汇编分析更细的问题。如果程序还在跑,可以这样挂上去:

sudo gdb -p PID

在 GDB 里执行continue让进程继续跑,等到问题复现。需要注意两点:一是对生产环境重要进程执行 gdb -p 会暂停进程,虽然可以 continue,但极短的停顿对在线服务也可能造成抖动,尽量在低峰期操作;二是让 core dump 能生成的话,要先设置:

ulimit -c unlimited

不要忘记检查 core 文件生成路径,通过sysctl kernel.core_pattern查看。否则段错误程序跑崩了,你四处找 core,路径却指向 systemd-coredump 管理的目录,白忙一场。

5.5 ADB:嵌入式开发调试的瑞士军刀

在嵌入式、Android 或电视盒子类设备上调试,ADB 是绕不开的。最常用的几组命令:

adb devices adb -s 设备序列号 shell adb shell logcat -s MyApp:I adb push ./app.apk /data/local/tmp/ adb reverse tcp:8080 tcp:8080 adb install -r app.apk adb kill-server

多设备同时插在电脑上时,直接adb shell会报错提示有多台设备,必须加-s选设备序列号。adb reverse的作用是把设备上的端口映射到本机,调试 Web 页面时很实用。设备连不上时先怀疑 adb server 状态,执行adb kill-server再重新adb devices,一般能解决。这几个命令虽然不属于服务器运维核心,但做 Linux 系统的嵌入式方向完全离不开。

6. 现场问题速查记录:我踩过的那些坑

6.1 tail -f 看不到新日志

现象:日志文件确实在更新,但tail -f不输出。原因:日志轮转工具把 access.log 改名,tail 还抱着旧文件的 fd。解决:改用tail -F。这是我列为“新人必踩第一名”的坑,没有任何例外情况。

6.2 grep 命中但显示 Binary file matches

原因:文件中有 \0 字节,grep 判定为二进制。解决:加-a强制文本模式,或者用--include="*.log"先过滤再搜。不要因为这个问题就加-r盲目扫描,范围越大越容易被二进制文件干扰。

6.3 ps 看到的进程名完全对不上二进制

原因:进程用prctl或启动脚本用exec -a改了 argv[0]。解决:用readlink -f /proc/PID/exe看真实路径。排查恶意进程或“看不懂的异常进程”时,这条是杀手锏。

6.4 /etc/fstab 写错导致开机进 emergency mode

现象:重启后系统停在 emergency mode。原因:fstab 里某条挂载配置错误,文件系统挂载失败。解决:输入 root 密码进入维护模式,注释掉或修正错误行,然后mount -a验证。预防:修改 fstab 之前先备份,改完用findmnt --verify检查语法。

6.5 NFS 失联,所有进程呈 D 状态,kill 不掉

现象:load average 飙升,ps 里大量 D 状态进程。原因:NFS server 宕机或网络中断,硬挂载的进程阻塞在 IO 上。解决:先恢复网络或 NFS 服务,再用umount -l摘除挂载点,实在不行重启对端服务。在线事务型应用不要把核心数据目录直接放 NFS,集群文件系统另选方案。

6.6 新建用户无法 sudo

现象:用户明明在 sudo 组,却提示 not in the sudoers file。原因:要么组名不对(Ubuntu 是 sudo,CentOS 是 wheel),要么usermod -G覆盖了原由的附加组。解决:确认发行版默认 sudo 组,使用usermod -aG 组名 用户,并visudo -c校验。

下面这张速查表是我贴在工位上的一份常用对照,适合打印出来:

现象典型命令补充说明
端口被占用ss -tulnp优先用 ss,不用 netstat
哪个目录占空间du -h --max-depth=1配合 sort -h 看从大到小
文件删了空间没释放lsof +L1找被删除但仍打开的文件
日志只追新不追旧tail -F处理轮转日志必须用大写 F
进程真实路径readlink -f /proc/PID/exe比 ps 输出更可靠
容器内看宿主机进程docker top不要只在容器里看 ps
分析访问日志 Top IPcut -d' ' -f1 log | sort | uniq -c | sort -rn必须先 sort 再 uniq

我个人在这些命令上花的冤枉时间不算少,所以最后再分享一个小习惯:不要试图把命令背全,而是围绕“问题类型”去建自己的速查脚本。比如我会在~/.bashrc里放几个 alias,alias ports='ss -tulnp'、alias du1='du -h --max-depth=1 | sort -h'、alias zz='ps -A -o stat,ppid,pid,cmd | awk '\''$1 ~ /^Z/{print}'\'''。遇到不确定的参数,先tldr 命令名看简单示例,必要时再翻 man。命令只是手,排查思路才是脑,把每个命令当成一次“提问”,问得越准,定位的速度就越快。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询