1. 摸清机器底细:接手一台陌生服务器,先看这四条命令
第一次拿到一台服务器,或者隔了几个月再次登录,我从来不会直接开始翻代码、查日志,而是先用一组命令把机器当前的“身体状况”摸一遍。这个习惯帮我省过很多次“排查半天发现是内存不够”的冤枉路。
硬件层面需要看四个维度:CPU、内存、磁盘、系统版本。
- CPU:
lscpu,查看核心数、型号、架构。后端服务选线程池大小、数据库调优都要以它为起点。 - 内存:
free -h,-h表示以人类可读的 GB/MB 形式显示。重点关注available那一列,它才是真正可用的内存,而不是只看free。 - 磁盘:
df -h,看各分区使用率。这条命令会在第五章详细展开,但开机时快速扫一眼,能避免你后面写数据时才发现磁盘满了。 - 系统版本:
cat /etc/os-release,确认发行版和版本号。装软件、换软件源、找兼容的安装包都要先确认它。
1.1 硬件与系统信息:lscpu、free -h、uname -a
lscpu 的输出有一大段,但新手只需要抓几个关键字段:CPU(s) 是逻辑核心总数,Model name 是具体型号,Architecture 是架构(大部分云主机都是 x86_64,遇到 aarch64 说明是 ARM 架构)。比如你拿到一台 8 核的机器,跑 Nginx + PHP-FPM 时进程数通常可以参考核心数来设置。
free -h 输出里有个容易误读的点:free 列显示的是“完全没用”的内存,数值通常很小,而 buff/cache 列会很大。很多人看到内存占用 90% 就紧张,其实那部分缓存是 Linux 为了提高文件读写速度而主动占用的,在需要时会自动释放。真正要看的是 available 列,它才是应用能拿到的剩余内存。
uname -a 则是一条命令汇总内核版本、主机名、系统时间等信息。内核版本在排查驱动兼容性、容器运行问题时经常要用。如果你只需要知道内核版本,可以简写为 uname -r。
1.2 登录与负载:uptime、who、w
uptime 除了告诉你系统运行了多久,还能同时显示当前时间、登录用户数和三个负载平均值:
code复制负载均值格式: 1分钟负载 5分钟负载 15分钟负载
负载值要结合 CPU 核心数理解。比如 4 核机器,负载 4.0 意味着 CPU 刚好饱和;负载 8.0 说明任务排队,明显过载。15 分钟负载比 1 分钟负载更能反映长期趋势——如果 15 分钟负载很高但 1 分钟负载降下来了,说明刚才高峰已经过去,机器正在恢复。
who 和 w 用来查看谁登录了系统。w 输出更详细,会列出每个登录用户的终端、登录时间、当前执行的命令。排查问题时,看到某个陌生 IP 或陌生用户登录,就要警惕了。我处理过一次服务器被入侵的现场,最初线索就是 w 命令里出现了一个我从不认识的用户名。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 文件操作基本功:ls、cp、mv、rm 的用法与边界
文件操作是 Linux 使用频率最高的一组命令,但恰恰是这种“天天用”的命令,最容易出现认知盲区。很多人会 ls 列出文件、cp 复制文件、mv 移动文件、rm 删除文件,但真正到了生产服务器上操作时,几个隐藏参数和边界条件搞不清楚,就会闯祸。
2.1 ls 的高频选项和排序技巧
ls 的完整参数非常多,但日常够用的集中在这几个:
ls -l:长格式显示,包含权限、属主、大小、修改时间。ls -a:显示所有文件,包括以.开头的隐藏文件。ls -h:文件大小以 K/M/G 等单位显示,配合-l使用。ls -t:按修改时间从新到旧排序,排查“哪个文件最新被改过”时很好用。ls -S:按文件大小从大到小排序,快速找出目录里的“大块头”。
我习惯把组合写成 ls -lht,一次拿到权限、大小、时间,还能让最新修改的文件排在最上面。查看大目录时,ls -lhS | head -20 能直接看见占用空间最大的前 20 个文件,比挨个翻快得多。
ls 还支持通配符。ls *.log 列出所有日志文件,ls file{1..3}.txt 展开成 file1.txt、file2.txt、file3.txt,ls file[0-9].log 匹配单个数字。通配符在批量操作时威力巨大,但也要小心,rm *.log 里的通配符一旦展开错了,后果难以挽回。
2.2 cp、mv 的隐藏细节
cp 默认不会复制目录,复制目录必须加 -r。复制时需要注意权限和时间戳:默认情况下,cp 创建的新文件属主是当前用户,修改时间是当前时间。如果要在服务器间同步配置、保留原始属性,要用 cp -p 保留权限和修改时间,或者直接用 cp -a 保留所有属性(等价于 -dR --preserve=all)。
mv 有两个完全不同的底层逻辑:在同一文件系统内移动,本质是“改名”,速度极快;跨文件系统移动,本质是“复制+删除”。这就导致一个经典问题:当你 mv 一个大文件到另一个挂载点(比如从系统盘移到数据盘)时,耗时很长,而且一旦中途失败,源文件可能已经部分消失。判断是否跨文件系统,可用 df 看源目录和目标目录是否在同一个挂载点上。
mv 还有一个容易被忽略的场景:目标文件已存在时,mv 会直接覆盖而不提醒。如果想把文件移动到某个有同名文件的目录,建议先 ls 确认目标目录,或者加上 -i 参数让命令在覆盖前询问。
2.3 rm 的安全习惯与事故复盘
rm 是 Linux 里最危险的命令之一。生产环境里我见过不止一次因为 rm -rf 打错路径导致目录被删空的事故。几个必须养成的习惯:
- 不要用
rm -rf处理不确定路径。先ls确认,再执行删除。 - 删除前使用
rm -i,让系统逐个确认。批量删除时可能有点烦,但比误删好一万倍。 - 重要目录可以先打包备份再删:
tar czf backup.tgz /path/to/dir,再执行删除,心里有底。 - 处理文件名包含空格或特殊字符的文件时,用双引号包裹或使用 Tab 键自动补全,避免被 shell 误解析。
rm 删除文件后,数据无法通过命令直接恢复(除非事先有备份或使用了支持恢复的文件系统)。所以,真正重要的数据一定要走备份流程,不要寄希望于“删错了能找回来”。
3. 权限与归属:chmod、chown 和特殊权限位的真实用途
权限管理是 Linux 多用户系统的基石。刚接触 Linux 的新手最容易犯的错,就是遇到权限报错直接 chmod 777。这个习惯在个人虚拟机里问题不大,但在服务器上等于把大门钥匙复制给所有人,经常成为安全漏洞的根源。
3.1 数字权限与符号权限的换算
Linux 权限分三组:属主(u)、属组(g)、其他用户(o),每组三个权限位:读(r=4)、写(w=2)、执行(x=1)。数字权限就是把这三组按位权相加:
| 权限组合 | 数字 | 说明 |
|---|---|---|
| rwx | 7 | 读、写、执行 |
| rw- | 6 | 读、写 |
| r-x | 5 | 读、执行 |
| r-- | 4 | 只读 |
| --- | 0 | 无权限 |
所以 chmod 755 file 的含义是:属主可读写执行(7),属组可读执行(5),其他人可读执行(5)。这是常见的可执行文件权限。chmod 644 file 是普通文件默认权限,属主可读写,其他人只读。
符号权限的可读性更强:chmod u+x script.sh 给属主加执行权限,chmod g-w file 去掉属组的写权限,chmod a+r file 让所有人获得读权限。日常维护中,我更推荐符号方式,因为它只改你想改的位,不容易手滑把整个权限覆盖掉。
修改属主和属组用 chown:chown user:group file,只改属主用 chown user file,只改属组用 chown :group file。注意,普通用户不能把文件 chown 给别人,只有 root 能这么做。
3.2 setuid、setgid、sticky 位的作用
除了 rwx 三组权限,Linux 还有三个特殊权限位,分别对应文件权限前的 s 和 t,它们的行为让你能理解一些“为什么这个文件能被执行”的疑问。
- setuid(
chmod u+s file或chmod 4755 file):文件执行时,进程以文件属主的身份运行,而不是执行者的身份。典型例子是/usr/bin/passwd,普通用户改密码时要写/etc/shadow,这个文件属主是 root,正是靠 setuid 位让临时提升权限成为可能。 - setgid(
chmod g+s dir或chmod 2755 dir):作用于目录时,目录里新建的文件自动继承目录的属组。团队协作目录常用这个技巧,避免每个新文件都要手动改一次属组。 - sticky 位(
chmod +t dir或chmod 1777 dir):作用在目录上时,目录里的文件只有属主、目录属主或 root 才能删除。/tmp目录就是典型例证——所有用户都能写,但谁都不能删别人的临时文件。
3.3 排查异常权限的实战命令
在巡检或应急时,以下几条命令能快速发现权限异常:
- 查找所有 setuid 文件:
find / -perm -4000 2>/dev/null。这类文件是提权攻击的高发目标,定期检查是安全的良好习惯。 - 查找所有全局可写文件:
find / -perm -0002 -type f 2>/dev/null。 - 查找属主或属组异常的文件:
find / -user root -group root -type f 2>/dev/null(按需修改用户名)。
我自己处理过一次“某个目录里的文件总是被别人删除”的工单,排查半天才发现目录权限是 777。改回 755 并调整属组后问题消失。这个过程中也确认了:chmod 777 并非完全被禁止,但必须知道它带来的后果,并且只在真正需要共享读写而又无法用 ACL 或属组管理时才考虑。
4. 系统变慢时:top、ps、kill 的配合排查
服务器响应变慢,是运维和开发都会遇到的高频问题。正确的排查思路不是“重启大法”,而是按顺序回答三个问题:哪个进程在消耗资源?消耗的是什么资源?这个进程能不能安全处理?
4.1 top 的实时观察
top 是实时查看系统状态的工具。默认按 CPU 使用率排序,进入交互界面后可以用几个快捷键切换视角:
P:按 CPU 使用率排序。M:按内存占用排序。T:按累计 CPU 时间排序。1:展开每个核心的负载。s:修改刷新间隔,排查时我常改成 1 秒。q:退出。
top 上半部分的 load average、%Cpu(s) 和内存使用情况同样重要。如果 %Cpu(s) 中 us(用户态)很高,说明是应用在消耗资源;如果 sy(系统态)很高,可能是内核层面或系统调用频繁;如果 wa(I/O 等待)很高,磁盘可能成了瓶颈,CPU 在等磁盘响应。
4.2 ps 的静态快照与排序
top 适合实时观察,ps 则适合抓取某一时刻的进程快照,并配合 grep 精确定位。常用组合:
ps aux:列出所有进程,用USER、PID、%CPU、%MEM、START、COMMAND等列展示。ps -ef:另一种格式,展示父进程 ID(PPID),排查进程父子关系时有用。ps aux --sort=-%cpu | head -10:按 CPU 占用从高到低取前 10。ps aux --sort=-%mem | head -10:按内存占用从高到低取前 10。
定位到进程后,如果想知道进程的具体启动命令、工作目录,可以用 ls -l /proc/PID/cwd 看进程的工作目录,/proc/PID/cmdline 看启动参数。/proc 伪文件系统在排查时真的能救命。
4.3 kill 的正确时机与信号选择
kill 命令本质是向进程发送信号。默认发送 TERM(15)信号,请求进程“体面地退出”。进程收到后可以先保存状态、释放资源,然后自行关闭。绝大多数应用进程应该先用 kill(TERM)而不是直接 kill -9。
只有在进程完全没有响应、无法正常退出时,才使用 KILL(9)信号。kill -9 是强制杀死,进程没有机会做任何清理,可能导致数据写入不完整、临时文件残留等问题。数据库、消息队列这类有状态服务尤其忌讳直接 kill -9,轻则丢数据,重则启动时恢复半天。
查看进程可以使用的信号列表:kill -l。排查中还会遇到“kill 不掉”的进程,常见原因有两种:进程处于不可中断的内核态等待(D 状态),或者进程是僵尸进程(Z 状态,父进程未回收)。D 状态的进程往往伴随着磁盘 I/O 或网络 I/O 异常,解决根因比反复 kill 更有效。僵尸进程无法通过 kill 清除,需要等它的父进程退出或者父进程调用 wait 回收。
5. 磁盘告警:df、du、lsof 三项定位空间去向
磁盘空间满是一个高频故障,现象非常直白:写文件报错、服务异常、日志刷不进去。但“满”的原因比想象中复杂,有时候 df 显示满了,du 加起来却找不到大文件,这时候就要用到隐蔽的定位技巧。
5.1 df:先看分区和 inode
df -h 查看文件系统空间使用情况。这里的重点不是记住参数,而是理解“分区”概念:一台机器上可能有多个挂载点,每个挂载点对应一个独立的分区。查看 /data 目录时,要知道它落在哪个挂载点上,别把 / 分区的剩余空间当成 /data 的。
还有一个容易被忽略的是 inode 用完。df -i 查看 inode 使用率。inode 是文件系统存储文件元信息的结构,小文件、零散文件过多时,可能出现“空间还很多但无法创建新文件”的现象。500G 硬盘,全是几 KB 的缓存文件,几百万个 eventually inode 就耗尽了。处理方法是清理大量小文件,或者重新规划分区。
5.2 du:从大到小找大头
du 用来统计目录和文件占用的实际空间。常用组合:
du -sh * | sort -rh | head -20:当前目录下各文件和子目录的空间占用,从大到小排出前 20。du -h --max-depth=1 /var 2>/dev/null:只看一层子目录,快速定位大目录。du -sh /var/log:直接查看某个目录总大小。
排查磁盘空间的经典流程是:先从根目录开始 du -sh * 找出最大的目录,再逐层深入。这个过程不是每次都能很快结束,但 90% 的情况能在三层以内找到占地大户。日志文件是常见的元凶,找到后先确认是否可以清理,再用 truncate -s 0 /var/log/xxx.log 清空而不是直接删除——直接删除可能导致正在写入的进程继续往已删除的文件句柄里写,空间不会立即释放。
5.3 lsof:删除不释放的场景
这是最容易被忽略的一环。你删除了一个大文件,du 显示空间已经减掉,但 df 依然显示占用率很高。原因是:某个进程还持有这个文件的打开句柄,文件虽然被删除了,但文件系统没有真正释放空间,直到进程关闭这个句柄。
排查方法:lsof +L1,列出所有已被删除但仍被进程占用的文件。看到输出后,记住 PID,确认进程是否可以重启,重启后空间就会释放。这个场景常见于日志轮转,旧日志被删除后,正在写新日志的进程还握着旧文件句柄。如果服务不能重启,只能等它在某个时刻自然关闭文件句柄,或者用符号链接提前转移路径。
6. 网络不通时:ping、traceroute、ss、nc 的排查顺序
网络故障排查是最容易让人“打胡乱说”的地方。一会儿怀疑 DNS,一会儿怀疑防火墙,一会儿怀疑路由器。正确的做法是分层排查,按物理链路到应用链路的顺序一步步缩小范围。
6.1 分层排查的思路
网络模型可以简化为:目标 IP 是否可达 → 路由是否正常 → 端口是否监听 → 应用是否响应。
第一层是验证基本连通性:ping <目标IP>。ping 通说明 ICMP 协议可达,主机在网络层面是通的。但要注意,很多主机禁用了 ICMP,ping 不通不代表端口不通,所以不要轻易下结论。
第二层是路由跟踪:traceroute <目标IP> 可以看到数据包经过的每一跳,判断卡在哪一跳。国内网络环境下,跨运营商时经常出现中间节点丢包或延迟增高的情况,traceroute 能帮你区分“问题在本机还是出在中间链路”。mtr 是 traceroute 的增强版,持续检测每一跳的丢包率,比单次 traceroute 更有判断价值。
6.2 ss 和 nc 的端口检查
确认网络链路没问题后,要检查目标端口是否在监听。ss 是现代 Linux 系统推荐的查看网络连接工具(netstat 是它的前辈,很多新版系统已不再默认安装):
ss -lntp:查看所有监听的 TCP 端口和对应进程。其中-l表示监听,-n表示不解析域名(更快),-t表示 TCP,-p显示进程信息。ss -ulnp:查看 UDP 端口监听。ss -s:汇总当前连接状态,能看到大量 TIME_WAIT 或 ESTABLISHED 连接数。
nc(netcat)可以测试本机到目标端口是否通:nc -vz <目标IP> <端口>。-v 显示详细信息,-z 只测试端口不发送数据。这个命令等效于 telnet 的端口探测,但可以很方便地用在脚本里做批量检查。
6.3 curl 验证实际服务
端口通了,还得确认服务本身是否正常。curl 是应用层验证的第一选择:
curl -I https://example.com:只看 HTTP 响应头,快速确认状态码。curl -v https://example.com:显示连接过程的详细内容,包括 DNS 解析结果、TLS 握手信息、HTTP 头。curl -k https://example.com:跳过证书验证,适合排查证书导致的访问问题。curl --connect-timeout 5 --max-time 10 https://example.com:限制连接和总耗时,避免命令长时间挂死。
curl -v 的输出会完整展示 DNS 解析结果,这在排查“域名解析到旧 IP”时特别有效。如果 DNS 解析出的 IP 不对,那问题大概率在 DNS 层面,而不是服务本身。
7. 日志分析三件套:grep、sed、awk 的组合使用
日志是运维和排查问题的第一手资料,但日志文件动辄几百 MB,直接打开看等于大海捞针。合理使用 grep、sed、awk,可以让日志分析变得“快、准、狠”。
7.1 grep:筛选和计数
grep 的核心是过滤。常用组合:
grep 'error' application.log:找包含 error 的行。grep -i 'error' application.log:忽略大小写。grep 'ERROR' application.log | grep -v 'healthcheck':先筛选,再排除干扰项。grep -E 'ERROR|FATAL' application.log:使用扩展正则匹配多个关键词。grep -c 'ERROR' application.log:统计匹配行数,秒出结果。grep -n 'ERROR' application.log:显示行号,方便定位上下文。
排查时间范围时,虽然不能直接用 grep 做时间比较,但可以先通过时间前缀筛选。比如日志每行以 2025-06-01 10:30 开头,用 grep '^2025-06-01 10:3[0-5]' 就能提取 10:30 到 10:35 之间的日志,非常实用。
7.2 sed:替换和取样
sed 是个流编辑器,擅长按行处理文本。日志分析中最常用的是两种场景:
一是取样。文件有几千行,不需要全看,sed -n '100,150p' application.log 只看第 100 到 150 行;sed -n '201p' a.log 只看第 201 行。其中 -n 表示不自动打印所有行,p 表示打印匹配行。
二是替换。把日志里的敏感信息用占位符替换后传给同事看,sed 's/phone_number/XXXX/g' a.log;或者对 IP 地址做匿名化处理,sed -E 's/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/IP/g' a.log。sed -i 可以直接改文件,但千万别在大文件上忘加备份:sed -i.bak 's/old/new/g' file 会先备份原文件再修改。
7.3 awk:提取列和统计
awk 擅长处理按分隔符分列的文本。日志格式通常是空格分隔,awk '{print $1, $2}' 就提取每行的前两列,{print $NF} 提取最后一列。指定分隔符用 -F,比如处理 CSV:awk -F',' '{print $1}'。
awk 最强大的能力是统计。分析访问日志时,统计独立 IP 数和每个 IP 的请求次数是一行命令的事情:
bash复制awk '{print $1}' access.log | sort | uniq -c | sort -rn
这条命令先把每行第一列(IP)提取出来,sort 排序,uniq -c 计数,最后 sort -rn 按次数从高到低排列。同理,统计某个接口的平均响应时间、最高耗时,也都可以用 awk 的累加逻辑实现:awk '{sum+=$NF} END {print sum/NR}' 计算最后一列的平均值。
三个工具各有分工:grep 负责筛行,sed 负责改和取,awk 负责列计算。结合使用时,管道把它们串起来,效率会非常高。
8. 命令行自救:man、history 和 alias 提升效率
最后一章聊的是“忘了命令怎么办”和“怎么减少重复劳动”。我在日常工作中见过很多开发者,遇到不熟的参数就上网搜,搜到一段代码复制进终端,但并不知道这段代码到底在做什么。Linux 自带的信息源和辅助工具其实已经足够解决绝大多数问题。
8.1 忘记参数时怎么办
几乎每条命令都有帮助文档。man <命令> 打开手册页,里面包含语法、参数、示例和注意事项。新手容易急着退出,可以先按 h 查看 man 的帮助,然后用 /关键词 搜索相关内容,按 n 跳到下一个匹配项,按 q 退出。
如果只想快速看参数而不想翻整篇,<命令> --help 或者 <命令> -h 通常就够了。man -k 是一个很容易被忽略的工具:man -k keyword 在手册页描述中搜索关键词。比如你想找“压缩”相关命令,man -k compress 会列出 gzip、xz、zip 等所有相关命令的名字和简介,先定位再细看。
8.2 历史命令的高效回放
终端输入的命令都会记录在 ~/.bash_history 中,history 命令可以查看历史记录。熟练使用几个技巧,效率提升不止一倍:
!!:执行上一条命令。输错命令想重跑时很方便。!$:展开上一条命令的最后一个参数。比如你刚跑过cat /etc/nginx/nginx.conf,下一条想编辑它,直接vim !$。!keyword:执行最近一条以 keyword 开头的命令。比如刚才跑过ping 8.8.8.8,现在输入!ping就会重新执行。Ctrl + r:反向搜索历史命令,输入关键字,连续按会依次匹配更早的记录。Ctrl + a/Ctrl + e:光标跳到行首 / 行尾,修改长命令时很顺手。Ctrl + u/Ctrl + k:从光标位置删到行首 / 行尾。
8.3 归档常用别名
别名(alias)能大幅减少重复劳动。查看当前已有的别名:alias。临时设置别名:alias ll='ls -lht'。但这样的别名只对当前终端会话有效,想永久生效,要写到 ~/.bashrc 中。
我自己的环境里常驻几个别名:
bash复制alias ll='ls -lht'
alias la='ls -A'
alias rm='rm -i'
alias grep='grep --color=auto'
alias ..='cd ..'
其中 rm='rm -i' 是我特别推荐的一个别名,它让删除操作每次都要确认,能在关键时刻阻止手滑。不过要注意,如果在命令中显式使用 /bin/rm 或者 rm -f,别名不会生效,所以别把 rm -i 当成万能保险。
配置完 .bashrc 后执行 source ~/.bashrc 使其立即生效。如果团队有统一环境,也可以把这些别名放到 /etc/profile.d/ 下的脚本里统一管理。
最后再分享一个小技巧。命令行里的很多操作其实可以“先想后敲”。每次要执行危险命令或者拿不准参数时,先按 Ctrl + u清空输入,想一想这条命令会不会影响正在运行的服务、会不会触发不可逆的操作。熟练之后,Linux 命令行的效率会远超过图形界面,而“无废话”的本质不是记住所有命令,而是知道在什么场景下该用哪几条、它们各自的边界在哪里。
