1. 为什么我建议你重新学一遍Linux命令
刚入行那会儿,我也觉得Linux命令嘛,翻来覆去就那几个,ls、cd、cat、grep,背下来就完事了。直到有一次线上环境出了状况,一台跑了关键业务的服务器负载突然飙到几十,SSH勉强能连上但敲个命令要等好几秒才响应。当时我脑子里第一反应是top,但top刷出来之后呢?哪个进程在捣乱?是CPU问题还是IO问题?内存够不够?磁盘满没满?网络有没有异常?一连串问题砸过来,我才发现自己对Linux系统管理的理解,停留在“会用”而不是“会查”。
这件事之后我花了很长时间重新梳理Linux系统管理的命令体系,不是按字母顺序背,而是按场景来组织——信息探查是一类,性能分析是一类,故障排查又是一类。每个场景下有哪些命令、这些命令看什么指标、指标异常说明什么问题、下一步该用什么命令继续深挖,形成一条完整的排查链路。这套方法论后来帮我解决了不少棘手问题,也让我在带新人的时候有了一个比较清晰的框架可以讲。
这篇文章就是把我这些年积累的Linux系统管理核心命令实战经验整理出来。不管你是刚接触Linux的新手,还是已经用了几年但排查思路不够系统的老手,应该都能从中找到一些有用的东西。我会从最基础的信息探查讲起,逐步深入到性能分析和故障排查,每个命令都会说清楚它解决什么问题、怎么看输出、什么情况下该用它。文章里涉及的所有操作都在测试环境验证过,你可以直接对照着在自己的机器上练习。
2. 信息探查:先搞清楚你在什么环境里
很多人拿到一台Linux机器就开始敲命令,但其实第一步应该是搞清楚这台机器的基本情况。操作系统版本、内核版本、硬件配置、网络环境,这些信息决定了后续你能用什么工具、该怎么分析问题。我见过有人在CentOS 6上找ss命令找不到,因为那个版本默认还是netstat;也见过有人在容器里用free看内存,结果看到的数字跟宿主机完全对不上。这些坑其实都可以通过前期的信息探查避免。
2.1 系统版本与内核信息:一切分析的前提
查看系统版本最常用的命令是cat /etc/os-release,这个文件在绝大多数现代Linux发行版上都存在,输出格式统一,包含发行版名称、版本号、ID等信息。相比lsb_release -a,它不依赖额外的包,在最小化安装的系统上也能用。如果你需要更详细的内核信息,uname -a会输出内核版本、主机名、硬件架构、编译时间等。这里有个细节:uname -r只输出内核版本号,在做脚本判断的时候更常用,因为输出干净,方便用cut或者awk截取。
# 查看发行版信息 cat /etc/os-release # 查看内核版本 uname -r # 查看完整系统信息 uname -a为什么内核版本这么重要?因为很多命令和内核特性是有版本依赖的。比如ss命令替代netstat是从内核3.x时代开始的,cgroup v2需要内核4.15以上,bpftrace需要内核4.9以上。如果你在排查问题的时候发现某个工具用不了,第一反应就应该是查内核版本,确认这个特性是否被支持。
还有一个容易被忽略的点:/proc/version文件也包含内核信息,但它和uname的区别在于,/proc/version里包含了编译器的版本信息。这个在排查一些诡异问题时偶尔会用到,比如某些内核模块编译时用的GCC版本和当前系统不一致导致加载失败。
2.2 硬件资源概览:CPU、内存、磁盘一眼看清
搞清楚系统版本之后,下一步就是看硬件配置。CPU方面,lscpu是最直观的工具,它会列出架构、核心数、线程数、主频、缓存大小等信息。如果你只关心逻辑CPU数量,nproc更简洁。这里要注意的是,lscpu显示的CPU(s)是逻辑CPU总数,也就是物理核心数乘以超线程数。在做性能分析的时候,区分物理核心和逻辑核心很重要,因为超线程带来的性能提升并不是线性的。
# CPU详细信息 lscpu # 逻辑CPU数量 nproc # 内存使用情况(人类可读格式) free -h # 磁盘分区使用情况 df -hT # 块设备列表 lsblk内存方面,free -h是最常用的命令。但很多人只看used和free两列,其实available这一列才是关键。free显示的是完全未被使用的内存,而Linux会把大量空闲内存用作缓存(buff/cache),所以free很小并不代表内存不够。available是内核估算的、在不使用swap的情况下可供新进程使用的内存量,这个数字才真正反映内存压力。
磁盘方面,df -hT同时显示文件系统类型和使用率,-T参数很实用,能让你一眼看出哪些分区是ext4、哪些是xfs、哪些是tmpfs。lsblk则以树状结构展示块设备,能清楚看到磁盘和分区的关系,以及哪些分区挂载到了哪个目录。这两个命令配合使用,基本就能把存储布局摸清楚。
2.3 网络配置速查:IP、路由、端口一个不漏
网络信息探查的命令选择跟系统版本关系很大。老系统上ifconfig、route、netstat是标配,但新系统默认可能只装了iproute2工具集,对应的命令是ip addr、ip route、ss。我个人的习惯是统一用iproute2系列,因为输出更规范,而且功能更强。
# 查看所有网络接口 ip addr show # 查看路由表 ip route show # 查看监听端口 ss -tlnp # 查看所有连接 ss -tanpss -tlnp这个组合值得拆开说:-t表示TCP,-l表示监听状态,-n表示不解析服务名(直接显示端口号),-p表示显示进程信息。这四个参数组合起来,就能看到当前系统上所有正在监听的TCP端口以及对应的进程。排查“端口被占用”或者“服务没起来”这类问题时,这个命令基本是第一步。
ip addr show的输出里,需要重点关注的是接口状态(UP/DOWN)、IP地址、子网掩码、MTU值。MTU在排查网络性能问题时很关键,如果MTU设置不当,可能会导致大包被分片,影响传输效率。ip route show则告诉你默认网关是谁、有哪些静态路由,在排查跨网段通信问题时必不可少。
注意:在容器环境中,
ip addr看到的网络接口和宿主机可能完全不同。容器通常有自己独立的网络命名空间,看到的eth0其实是veth pair的一端。如果需要查看宿主机的网络配置,需要进入宿主机的命名空间或者使用nsenter工具。
3. 性能分析:用数据说话,别靠猜
信息探查解决的是“我有什么”的问题,性能分析解决的是“它现在怎么样”的问题。这两者的区别在于,信息探查是静态的、一次性的,性能分析是动态的、需要持续观察的。很多人在排查性能问题时容易犯一个错误:只看一眼top就下结论。但性能问题往往是波动的,单次采样很可能错过峰值。我的习惯是先用一个快速命令看全局,发现异常指标后再用更精细的工具深入分析。
3.1 CPU性能分析:从top到pidstat的递进思路
top是最常用的CPU分析工具,但很多人只用它看个大概。其实top的交互模式里有很多有用的功能:按1可以展开每个CPU核心的使用率,按P按CPU使用率排序,按M按内存使用率排序,按c显示完整命令行。这些快捷键在排查问题时能帮你快速定位到可疑进程。
# 启动top并展开CPU核心 top -1 # 批处理模式输出一次快照 top -bn1 | head -20 # 查看指定进程的CPU使用详情 pidstat -p <PID> 1 5top的输出里,需要重点关注的几个指标:us(用户态CPU时间)、sy(内核态CPU时间)、wa(IO等待时间)、id(空闲时间)。如果us很高,说明应用程序在消耗CPU;如果sy很高,可能是系统调用频繁或者内核在处理大量中断;如果wa很高,说明CPU在等IO,问题可能出在磁盘上。
pidstat是sysstat包里的工具,比top更适合做精细分析。pidstat -p <PID> 1 5会每秒采样一次,共采样5次,输出指定进程的CPU使用率。它的优势在于可以同时看到用户态和内核态的CPU占用比例,还能看到线程级别的数据(加-t参数)。在排查多线程程序的CPU问题时,pidstat -t能帮你定位到具体是哪个线程在消耗CPU。
3.2 内存与Swap分析:别被free的数字骗了
内存分析的核心是理解Linux的内存管理机制。前面提到过,free命令的available列比free列更重要。但除了看总量,还需要关注swap的使用情况。如果swap使用率持续增长,说明物理内存已经不够用了,系统在频繁换页,性能会急剧下降。
# 查看内存和swap使用 free -h # 查看内存统计详情 vmstat 1 5 # 查看指定进程的内存映射 pmap -x <PID> # 查看slab分配器使用情况 slabtop -ovmstat 1 5每秒输出一次,共5次。输出中的si和so两列分别表示从swap换入和换出的内存量(KB/s)。如果这两个值持续大于0,说明系统正在频繁使用swap,需要警惕。bi和bo表示块设备的读写量,如果这两个值很高而CPU的wa也很高,说明IO是瓶颈。
pmap -x <PID>可以查看指定进程的内存映射详情,包括每个内存段的地址、大小、RSS(常驻内存集)、脏页数量等。在排查内存泄漏时,这个命令能帮你看到进程的内存到底花在了哪里。slabtop则用于查看内核slab分配器的使用情况,如果发现某个slab缓存异常大,可能是内核模块有内存泄漏。
实操心得:在容器环境中,
free命令看到的内存信息可能不准确,因为容器通常没有独立的/proc/meminfo。更可靠的方式是查看cgroup的内存限制和使用量,路径通常在/sys/fs/cgroup/memory/下。如果是cgroup v2,路径是/sys/fs/cgroup/<group>/memory.current和memory.max。
3.3 磁盘IO分析:iostat和iotop的配合使用
磁盘IO问题往往表现为系统变慢,但CPU使用率不高。这时候iostat和iotop就是主要工具。iostat -x 1会每秒输出一次扩展统计信息,重点关注%util(设备利用率)、await(平均等待时间)、r/s和w/s(每秒读写次数)。
# 磁盘IO统计,每秒一次 iostat -x 1 # 按进程查看IO使用 iotop -o # 查看磁盘分区IO详情 iostat -p sda 1%util接近100%说明磁盘基本跑满了,await如果远大于svctm(服务时间),说明IO请求在队列里排队严重。iotop -o只显示有IO活动的进程,按IO使用率排序,能快速定位到是哪个进程在大量读写磁盘。
这里有个经验:如果iostat显示磁盘利用率很高,但iotop里看不到明显的IO进程,可能是内核线程在做IO(比如回写脏页)。这时候可以查看/proc/vmstat里的nr_dirty和nr_writeback,如果这两个值很大,说明有大量脏页正在回写,可能需要调整内核的脏页回写参数。
3.4 网络性能分析:带宽、连接数、重传率
网络性能分析主要看三个维度:带宽使用率、连接数、重传率。带宽可以用sar -n DEV 1查看,连接数用ss -s看统计摘要,重传率用netstat -s或者ss -ti看TCP详细信息。
# 网络接口带宽统计 sar -n DEV 1 5 # 网络连接统计摘要 ss -s # TCP重传统计 netstat -s | grep -i retrans # 查看指定连接的TCP详情 ss -ti dst 10.0.0.1sar -n DEV 1 5每秒输出一次各网络接口的收发字节数和包数。如果某个接口的txkB/s或rxkB/s接近网卡带宽上限,说明带宽是瓶颈。ss -s输出的统计摘要里,estab表示已建立的连接数,如果这个数字异常大(比如几万),可能是连接泄漏或者遭受了连接洪水攻击。
TCP重传率是判断网络质量的重要指标。netstat -s | grep -i retrans会显示重传的段数和百分比。正常情况下重传率应该低于0.1%,如果超过1%说明网络质量有问题。ss -ti可以查看单个连接的TCP内部状态,包括RTT、拥塞窗口、重传次数等,在排查具体连接的问题时很有用。
4. 故障排查:从现象到根因的完整链路
故障排查是Linux系统管理中最考验功力的部分。它不像信息探查那样有固定的命令清单,也不像性能分析那样有明确的指标体系。故障排查更像是一个侦探过程:从现象出发,提出假设,用命令验证假设,逐步缩小范围,最终找到根因。这一章我会用几个典型场景来展示这个思路。
4.1 系统负载高但CPU空闲:谁在捣乱
“负载高但CPU空闲”是Linux系统管理里一个经典的反直觉现象。uptime显示的负载值包含了正在运行和等待运行的进程数,而等待IO的进程也会被计入负载。所以如果磁盘IO很慢,大量进程在等IO,负载就会很高,但CPU其实是空闲的。
# 查看系统负载 uptime # 查看运行队列和阻塞进程 vmstat 1 5 # 查看处于D状态的进程 ps -eo pid,stat,comm | awk '$2 ~ /D/' # 查看IO等待 iostat -x 1排查这个问题的第一步是vmstat,看r列(运行队列)和b列(阻塞进程)。如果r列不高但b列很高,说明大量进程在阻塞等待。然后用ps -eo pid,stat,comm | awk '$2 ~ /D/'找出处于D状态(不可中断睡眠)的进程。D状态通常意味着进程在等待IO,可能是磁盘IO、NFS挂载、或者某些内核锁。
找到D状态进程后,可以用cat /proc/<PID>/stack查看内核栈,了解它到底在等什么。这个文件需要root权限才能读取。如果内核栈显示在等IO,再结合iostat确认是哪个磁盘的问题。如果是NFS挂载导致的D状态,可能需要检查NFS服务器的状态或者调整挂载参数。
注意:D状态的进程无法被kill -9杀死,因为它们不响应信号。如果确认是某个挂载点的问题,可能需要先卸载挂载点或者重启系统。这也是为什么在生产环境中,NFS挂载一定要加
soft和timeo参数,避免进程无限期阻塞。
4.2 磁盘空间满了但找不到大文件:被删除的文件还在占空间
“磁盘满了但找不到大文件”是另一个常见问题。用df -h看到某个分区使用率100%,但用du -sh逐层统计却找不到对应大小的文件。这种情况通常是因为有文件被删除了,但仍有进程持有文件句柄,导致磁盘空间没有释放。
# 查看磁盘使用率 df -h # 查找被删除但仍被占用的文件 lsof +L1 # 或者用lsof查看指定进程打开的文件 lsof -p <PID> | grep deletedlsof +L1会列出所有link count小于1的文件,也就是被删除但仍有进程打开的文件。输出中的SIZE/OFF列显示文件大小,NAME列显示文件路径(通常带有(deleted)标记)。找到这些文件后,可以重启对应的进程来释放空间,或者用> /proc/<PID>/fd/<FD>的方式清空文件内容(注意这会截断文件,可能影响进程运行)。
这个问题的根源在于Linux的文件管理机制:文件的数据存储在磁盘上,文件名和inode的对应关系存储在目录项中。删除文件时,目录项被移除,但inode和数据块只有在所有打开该文件的进程都关闭句柄后才会被释放。所以只要还有进程持有句柄,磁盘空间就不会释放。
4.3 服务无法启动:端口、权限、依赖逐项排查
服务启动失败的原因很多,但排查思路可以归纳为“三层检查”:端口是否被占用、权限是否足够、依赖是否满足。
# 检查端口占用 ss -tlnp | grep <端口号> # 检查文件权限 ls -la /path/to/service/binary # 检查服务依赖 ldd /path/to/service/binary # 查看服务日志 journalctl -u <服务名> -n 50端口占用是最常见的原因。ss -tlnp | grep <端口号>能快速确认端口是否已被其他进程监听。如果被占用,输出会显示进程PID和名称,你可以决定是停掉占用进程还是修改服务配置。
权限问题通常出现在服务以非root用户运行时。检查二进制文件是否有执行权限、配置文件是否可读、日志目录是否可写、数据目录是否可读写。ls -la看文件权限,namei -l /path/to/file可以逐级检查路径上每个目录的权限。
依赖问题包括动态库缺失和外部服务不可用。ldd /path/to/binary会列出二进制依赖的所有动态库,如果有not found的条目,说明缺少对应的库。外部服务依赖比如数据库、缓存、消息队列等,需要检查网络连通性和服务状态。
journalctl -u <服务名> -n 50查看systemd管理的服务日志,-n 50表示显示最近50行。如果服务不是systemd管理的,日志可能在/var/log/下的某个文件里,或者通过strace跟踪系统调用来定位问题。
4.4 网络不通:分层排查法
网络不通的排查需要分层进行,从物理层到应用层逐层确认。虽然Linux系统管理主要关注主机层面,但了解整个链路有助于快速定位问题。
# 第一层:网卡状态 ip link show # 第二层:IP和路由 ip addr show ip route show # 第三层:连通性 ping -c 3 <目标IP> # 第四层:端口可达性 nc -zv <目标IP> <端口> # 第五层:DNS解析 dig <域名> +short nslookup <域名>第一层看网卡是否UP,如果网卡是DOWN状态,可能是驱动问题或者网线没插好。第二层看IP和路由是否正确,如果路由表里没有到达目标网段的路由,包就发不出去。第三层用ping测试ICMP连通性,如果ping不通但IP配置正确,可能是中间网络设备拦截了ICMP。第四层用nc -zv测试TCP端口是否可达,这个比ping更能反映实际服务的可达性。第五层检查DNS解析,如果域名解析不了,应用层自然连不上。
traceroute或者mtr可以查看包经过的每一跳,帮助定位问题出在哪个网络节点。tcpdump则可以在本机抓包,确认包是否发出、是否收到响应。这两个工具在排查复杂网络问题时非常有用。
实操心得:在排查网络问题时,我习惯先用
ss -s看本机的连接统计,确认不是本机连接数爆满导致的。然后用ip -s link看网卡的收发统计,确认没有大量错误包或丢包。这两个快速检查能排除掉很多本机层面的问题。
5. 我的排查工具箱与常用组合
前面几章分别讲了信息探查、性能分析和故障排查,这一章我想分享一下我日常工作中最常用的命令组合,以及一些提高效率的小技巧。这些组合不是固定的公式,而是根据经验总结出来的“起手式”,能帮你快速进入排查状态。
5.1 一分钟快速体检:五个命令看全局
当你登录到一台不熟悉的机器,或者感觉系统“有点不对劲”但说不上哪里不对时,这套组合能在最短时间内给你一个全局印象。
# 1. 系统负载和运行时间 uptime # 2. 内存和swap free -h # 3. 磁盘使用率 df -hT # 4. CPU和内存TOP进程 top -bn1 | head -20 # 5. 网络连接统计 ss -s这五个命令执行下来不超过10秒,但能覆盖负载、内存、磁盘、进程、网络五个维度。如果所有指标都正常,那问题可能不在系统层面,需要往应用层排查。如果某个指标异常,再针对性地深入分析。
我个人的习惯是把这五个命令写成一个shell函数,登录后直接敲一个短命令就能全部执行。这样既省时间,又不会漏掉某个维度。
5.2 进程级深入分析:从ps到strace
当快速体检发现某个进程可疑时,就需要对它进行深入分析。这个过程通常是:先看进程的基本状态,再看它的资源使用,最后用strace跟踪它的系统调用。
# 查看进程基本信息 ps -p <PID> -o pid,ppid,user,stat,start,time,cmd # 查看进程打开的文件 lsof -p <PID> # 查看进程的网络连接 ss -tanp | grep <PID> # 查看进程的环境变量 cat /proc/<PID>/environ | tr '\0' '\n' # 跟踪进程的系统调用 strace -p <PID> -T -ttps -p <PID> -o ...可以自定义输出格式,只看你关心的字段。lsof -p <PID>列出进程打开的所有文件,包括普通文件、目录、设备、socket等。ss -tanp | grep <PID>看进程的网络连接。cat /proc/<PID>/environ看进程的环境变量,在排查配置问题时很有用。
strace -p <PID> -T -tt附加到运行中的进程,跟踪它的系统调用。-T显示每个系统调用的耗时,-tt显示时间戳。如果发现某个系统调用耗时很长或者频繁失败,那就是问题的线索。不过要注意,strace会显著降低进程性能,在生产环境使用时要谨慎,尽量短时间跟踪。
5.3 日志分析:journalctl和grep的黄金组合
日志是排查问题最重要的信息来源之一。systemd管理的服务用journalctl查看,传统服务用grep在/var/log/下搜索。
# 查看指定服务的最近日志 journalctl -u <服务名> -n 100 --no-pager # 按时间范围查看日志 journalctl --since "2024-01-01 10:00:00" --until "2024-01-01 11:00:00" # 按优先级过滤 journalctl -p err -n 50 # 在日志文件中搜索关键词 grep -r "error" /var/log/ --include="*.log" | tail -50journalctl -u <服务名>查看指定服务的日志,-n 100显示最近100行,--no-pager避免进入分页模式(方便在脚本中使用)。--since和--until按时间范围过滤,在排查特定时间段的问题时很有用。-p err只显示错误级别及以上的日志。
对于传统日志文件,grep -r递归搜索,--include="*.log"限定文件类型,tail -50只看最后50条。如果日志文件很大,可以用awk按时间范围过滤,或者用sed截取特定行范围。
注意:
journalctl的日志默认存储在/var/log/journal/下,如果这个目录不存在,日志可能只存在内存中,重启后就丢失了。如果需要持久化日志,要确保/var/log/journal/目录存在并且systemd-journald配置正确。
5.4 我的常用别名和脚本片段
最后分享几个我日常使用频率最高的别名和脚本片段,能显著提高排查效率。
# 查看监听端口(带进程信息) alias ports='ss -tlnp' # 查看磁盘使用率(按使用率排序) alias dfh='df -hT | sort -k5 -rh' # 查看内存使用最高的10个进程 alias memtop='ps -eo pid,comm,%mem,rss --sort=-%mem | head -11' # 查看CPU使用最高的10个进程 alias cputop='ps -eo pid,comm,%cpu --sort=-%cpu | head -11' # 快速查找被删除但仍被占用的文件 alias deleted='lsof +L1 2>/dev/null'这些别名定义在~/.bashrc或者~/.bash_aliases里,登录后自动生效。ports比完整的ss -tlnp少敲很多字符,dfh按使用率排序能让你一眼看到哪个分区快满了,memtop和cputop快速定位资源消耗大户,deleted在排查磁盘空间问题时特别有用。
脚本片段方面,我常用一个函数来查看指定进程的详细信息:
pinspect() { local pid=$1 if [ -z "$pid" ]; then echo "Usage: pinspect <PID>" return 1 fi echo "=== Process Info ===" ps -p "$pid" -o pid,ppid,user,stat,start,time,%cpu,%mem,cmd echo "=== Open Files ===" lsof -p "$pid" 2>/dev/null | head -20 echo "=== Network Connections ===" ss -tanp 2>/dev/null | grep "$pid" echo "=== Environment ===" cat /proc/"$pid"/environ 2>/dev/null | tr '\0' '\n' | head -20 }这个函数把进程的基本信息、打开的文件、网络连接、环境变量集中输出,省去了逐个命令敲的麻烦。当然,实际使用中可以根据需要调整输出的详细程度。
6. 几个我踩过的坑和对应的解法
写了这么多命令和思路,最后我想分享几个实际工作中踩过的坑。这些坑在文档里通常不会写,但实际遇到的时候确实会让人抓狂。提前知道这些,能帮你省下不少排查时间。
6.1 时间不同步导致日志对不上
有一次排查一个分布式系统的问题,应用日志显示请求在10:00:00发出,但下游服务的日志显示10:00:05才收到。一开始以为是网络延迟,查了半天网络没问题。后来才发现是两台服务器的时间差了5秒。Linux服务器的时间同步通常由chronyd或ntpd负责,用timedatectl可以查看时间同步状态。
# 查看时间同步状态 timedatectl status # 查看chrony同步详情 chronyc sources -v # 手动同步时间 chronyc makesteptimedatectl status会显示System clock synchronized是否为yes,以及NTP service是否active。如果同步没开启,用timedatectl set-ntp true开启。chronyc sources -v显示时间源的详细信息,^*开头的行表示当前使用的同步源。chronyc makestep强制立即同步,适合在时间偏差较大时使用。
这个坑的教训是:排查跨主机问题时,第一步就应该确认各主机的时间是否同步。时间不同步不仅影响日志分析,还可能导致证书验证失败、定时任务执行异常等问题。
6.2 文件描述符耗尽导致服务拒绝连接
“Too many open files”是另一个常见错误。Linux默认的文件描述符限制是1024,对于高并发的服务来说远远不够。当文件描述符耗尽时,服务无法接受新连接,表现为“连接被拒绝”或“服务无响应”。
# 查看当前限制 ulimit -n # 查看系统级限制 cat /proc/sys/fs/file-max # 查看当前已使用的文件描述符数量 cat /proc/sys/fs/file-nr # 查看指定进程的文件描述符限制 cat /proc/<PID>/limits | grep "open files"ulimit -n显示当前shell的文件描述符软限制。/proc/sys/fs/file-max是系统级别的最大文件描述符数。/proc/sys/fs/file-nr的第一个数字是已分配的文件描述符数,第二个是未使用的,第三个是最大值。如果第一个数字接近第三个,说明系统级别的文件描述符快用完了。
修改文件描述符限制需要同时调整多个地方:/etc/security/limits.conf设置用户级限制,systemd服务需要在unit文件里设置LimitNOFILE,内核参数fs.file-max控制系统级上限。只改一个地方往往不生效,这是很多人容易忽略的。
6.3 磁盘inode耗尽但空间还有剩余
df -h显示磁盘空间充足,但创建文件时提示“No space left on device”。这种情况通常是inode耗尽了。每个文件都需要一个inode来存储元数据,如果文件数量太多(比如大量小文件),inode可能先用完。
# 查看inode使用情况 df -i # 统计指定目录下的文件数量 find /path/to/dir -type f | wc -l # 找出文件数量最多的目录 for dir in /path/to/dir/*/; do echo "$(find "$dir" -type f | wc -l) $dir"; done | sort -rn | head -10df -i显示inode的使用情况,IUse%列如果接近100%,说明inode快用完了。解决办法是删除不必要的文件,特别是临时文件、缓存文件、日志文件。如果确实需要大量小文件,可以考虑调整文件系统格式化时的inode数量,但这需要重新格式化,生产环境要谨慎。
预防inode耗尽的方法包括:定期清理临时目录、日志文件配置轮转和清理策略、监控inode使用率并设置告警。很多监控系统默认只监控磁盘空间,不监控inode,这是一个常见的监控盲区。
6.4 内核参数调整后不生效
有时候修改了/etc/sysctl.conf里的内核参数,执行sysctl -p后却提示某些参数不存在或者修改失败。这通常是因为参数名写错了,或者该参数在当前内核版本中不存在。
# 查看所有可用的内核参数 sysctl -a # 查看指定参数 sysctl net.ipv4.tcp_tw_reuse # 临时修改参数(立即生效,重启后失效) sysctl -w net.ipv4.tcp_tw_reuse=1 # 从配置文件加载 sysctl -p /etc/sysctl.confsysctl -a列出所有可用参数,如果某个参数不在列表里,说明当前内核不支持。sysctl -w临时修改,适合测试。sysctl -p从配置文件加载,但要注意配置文件里的语法必须正确,注释用#,参数和值之间用=或空格分隔。
还有一个容易忽略的点:某些参数是命名空间相关的,在容器里修改可能只影响当前命名空间,不影响宿主机。如果需要修改宿主机的参数,需要在宿主机的命名空间里操作。
7. 从命令到思路:构建自己的排查框架
写了这么多,其实我最想传达的不是某个具体命令怎么用,而是一种排查问题的思路。命令是死的,场景是活的。同样一个top命令,在不同场景下关注的重点完全不同。真正重要的是建立起一套自己的排查框架:遇到问题先看什么、再看什么、什么情况下该深入、什么情况下该换方向。
我的框架大致是这样的:先做信息探查,确认系统的基本情况;然后做快速体检,看五个核心指标是否正常;发现异常指标后,用对应的工具深入分析;分析过程中不断提出假设并用命令验证;找到根因后,不仅要解决当前问题,还要考虑如何预防同类问题再次发生。
这个框架不是一天建成的,是在一次次排查中慢慢积累起来的。每次遇到新问题,解决之后我都会花几分钟复盘:这次用了哪些命令、哪些命令没用上但可能有用、下次遇到类似问题能不能更快定位。这种复盘习惯比单纯背命令有用得多。
Linux系统管理是一个实践性极强的领域,看再多文章也不如自己动手操作一遍。建议你找一台测试机,把这篇文章里提到的命令都跑一遍,观察输出,理解每个字段的含义。遇到不理解的地方,用man命令查看手册,或者在网上搜索相关案例。积累到一定程度,你会发现排查问题越来越有章法,不再像无头苍蝇一样乱撞。
最后分享一个我个人的小习惯:我会维护一个“排查笔记”,记录每次遇到的典型问题和解决过程。笔记不用很正式,几句话描述现象、用了什么命令、发现了什么、怎么解决的就行。时间长了,这个笔记就成了我自己的排查手册,遇到类似问题时翻一翻,往往能快速找到思路。这个习惯坚持了几年,对我的帮助非常大,推荐你也试试。