Linux常用操作命令完全梳理:从敲不出命令到流畅排查问题
我做Linux运维这些年,最深的感受是:网上随便一搜就是各种"Linux常用操作命令大全",但大部分只是把man手册翻译了一遍,看的时候觉得都会,真到线上出问题时,还是不知道用哪条命令、输出该怎么解读。所以我一直觉得,命令本身不是重点,重点是理解每条命令的行为逻辑——它默认做了什么、输出里的每一列代表什么、在什么场景下会坑你。这篇文章我不会给你堆砌几百条冷门参数,而是按真实工作场景重新梳理Linux最常用、最高频的操作命令,每条都附上我实际使用时的习惯和踩过的坑。适合刚接触Linux的初学者,也适合用了两三年还依赖图形界面的开发者,跟着过一遍,能少走很多弯路。
1. 文件与目录操作:高频命令背后的行为逻辑
1.1 ls、cd、pwd:基础到容易被忽略的细节
Linux里打交道最多的对象就是文件,ls很可能是你敲出的第一个命令。但说实话,大多数人只会用ls看个文件名,顶多加个-l看权限,再往深了问就答不上来了。
先说ls -l的输出,第一列是权限位,总共10个字符,第一个字符表示文件类型:-是普通文件,d是目录,l是软链接,c是字符设备,b是块设备。后面9个字符分成三组,分别对应属主(owner)、属组(group)、其他人(others)的r读、w写、x执行权限。
这个权限位经常坑人。我遇到过不止一次:业务方说文件就在服务器上,程序却报Permission denied,登上去一看,文件权限是600,只有属主能读写,而程序是用另一个用户启动的。所以看到权限报错,第一反应不是怀疑防火墙,而是先看权限位,这个顺序很重要。
ls还有几个参数值得形成肌肉记忆。ls -lh里的-h会把文件大小显示成人类易读的K、M、G,而不是一堆字节数;ls -lt按修改时间倒序排列,排查"今天改了哪个配置文件"时特别好用;ls -la会显示包括以点开头的隐藏文件在内的所有文件。家目录下的.bashrc、.ssh这类隐藏配置,不加-a是看不见的。
cd命令这里补一个小技巧:cd -可以在最近两次所在目录之间来回切换,这在两个项目目录之间反复横跳时非常顺手,比重新输入一长串路径高效得多。另外注意pwd有两个版本,默认的pwd显示的是逻辑路径,也就是你cd进去时用的路径;pwd -P显示的是物理路径,会把软链接解析到底。我在排查那种"明明文件在A处,程序却说找不到"的问题时,pwd -P帮过大忙——当时项目里有一个软链接指向了旧版本的目录,服务启动脚本还在用旧路径拼接配置,pwd -P一执行,真实路径立刻现形。
1.2 cp、mv、rm:每个操作都要有安全意识
cp、mv、rm这三兄弟是日常最频繁的操作,同时也是事故高发区。
cp复制时一定要留意参数。复制目录必须加-r(递归),否则会报omitting directory。覆盖文件时默认不会提示,如果不想让同名旧文件被悄悄覆盖,加-i参数,每次覆盖前都会让你确认。批量复制时加-i尤其重要,我见过有人写脚本循环复制配置,结果旧配置被新配置覆盖得干干净净,回滚都没法回滚。
mv用来移动或重命名文件。这里有个反直觉的点:mv和cp不同,移动文件到另一个目录时,如果目标目录跨文件系统,底层其实是"先复制再删除",耗时和cp差不多;如果是在同一文件系统内,只是修改目录项指针,瞬间完成。所以看到mv大目录很慢时,别惊讶,先确认是不是跨分区了。
rm是真正的重灾区。rm -rf这条命令网上段子最多,但现实的残酷程度一点都不减。我的几条切身体会,每一条都是真金白银换来的:
第一,写rm -rf时,路径宁可多写也不要少写,尤其要警惕变量为空的情况。比如脚本里写了rm -rf $DIR/*,如果$DIR因为某种原因没取到值,这行命令就变成了rm -rf /*,后果自己想。稳妥的做法是脚本里先判断变量非空再执行,命令前加echo先打印要删除的路径,确认无误后再真正执行。
第二,能用mv代替rm就尽量代替。删除之前先mv file /tmp/trash/,把文件挪到回收目录,等系统稳定运行几天后再统一清理。这个习惯至少帮我恢复过三次误删场景——以为是废文件,删完第二天才发现还有用,从/tmp里捞回来就完事。
第三,实在要用rm删除大量文件时,配合find先查后删,后面会细讲。
1.3 find:多条件定位文件,比记忆参数更重要
find是被严重低估的命令。很多人只会find / -name "xxx",然后因为权限报错刷屏就放弃了。实际上find最强大的地方在于多条件组合,配合-type、-mtime、-size、-exec,几乎能解决所有文件定位问题。
先列几个高频场景。查找某个目录下30天前没动过的日志文件:
find /var/log -name "*.log" -mtime +30-mtime +30表示30天前修改过的文件,-mtime -1表示24小时内修改过的文件。这个参数在排查"到底哪个文件今天被改过"时极其好用。
查找超过500M的大文件:
find / -type f -size +500M-type f限定只找普通文件,这能过滤掉大量目录和设备节点,减少噪音。同样道理,查大目录时用-type d。
批量删除找到的文件:
find /var/log -name "*.log" -mtime +30 -delete我更推荐先用-exec echo做一次预演,确认范围没误伤,再把echo换成rm。例如:
find /var/log -name "*.log" -mtime +30 -exec echo {} \;执行find时还经常遇到一堆Permission denied报错,这是因为用普通用户搜了没有权限的目录。想静默跳过这些目录,命令末尾加2>/dev/null把错误输出丢掉就行,或者干脆用sudo执行。另外,find的-name参数是精准匹配文件名,想模糊匹配就要用通配符,比如*.log。
2. 文本处理三件套:grep、sed、awk的日常实战姿势
2.1 grep:过滤日志的正确打开方式
排查日志、搜索配置,grep绝对是出现频率最高的命令。但多数人只会grep "关键词" 文件,然后被一堆无关的匹配项淹没。
我几乎总是这样用grep:
grep -r "ERROR" /var/log/app/-r递归搜索目录下所有文件,适合不知道日志具体在哪个文件里的场景。-i忽略大小写,-v反向匹配(排除包含指定关键词的行),-n输出时带上行号,定位问题时直接能看到第几行出错。
.log文件非常长,只看关键词那一行往往不够,需要看上下文。grep -B 3 -A 5 "ERROR" app.log,把错误前3行、后5行的上下文一起打出来,这个参数组合排错时几乎必用。
还有一个容易被忽略的:grep -l只输出文件名,不输出匹配的具体内容。在批量搜索多个文件、想知道"哪些文件命中了关键词"时,-l比默认输出好用得多,输出干净利落。
grep默认支持基础正则,想用更复杂的正则时加-E(等同于egrep),比如匹配多个关键词:
grep -E "ERROR|FATAL|Exception" app.log从管道里接收数据是最常用姿势:tail -f配合grep实时过滤日志,ps配合grep查进程,cat配合grep查配置。逻辑很简单:前面的命令输出,后面的grep负责过滤。
2.2 sed:流式编辑,批量改配置的利器
sed像一台文本流水线,逐行读取、处理、输出。新手经常踩的第一个坑是:用sed 's/旧/新/g'改完文件,打开一看内容没变。因为sed默认把结果输出到屏幕,根本不会动原文件。真正要改文件必须加-i参数:
sed -i 's/127.0.0.1/0.0.0.0/g' /etc/app.conf-i是"原地修改"的意思,这个参数既有用又危险。我的习惯是执行前先不加-i跑一遍,把输出结果核对无误后再加上-i真正执行。批量修改几十台服务器的配置时,这个习惯能避免很多低级失误。
s是替换命令,格式为s/目标/替换值/,末尾的g代表全局替换每行所有匹配,不加g只替换每行第一处匹配。sed还经常用来查看文件的指定行范围:
sed -n '20,50p' app.log-n是"安静模式",只输出被处理过的行,p是打印。上面的命令会显示第20行到第50行。还有删除空行:
sed '/^$/d' file.txt总之,sed处理配置文件的批量替换是它最不可替代的场景,比如一次性把所有配置里的旧IP换成新IP,用编辑器手动改几十个文件容易漏,sed -i一行搞定。
2.3 awk:按列处理数据的瑞士军刀
awk比sed更进一步,它把每一行按分隔符拆成多个字段,按列处理数据。默认分隔符是空格或制表符,$0代表整行,$1代表第一列,$2代表第二列。
看一个经典场景,从/etc/passwd里提取用户名和用户ID:
awk -F: '{print $1, $3}' /etc/passwd-F:指定冒号为分隔符,因为passwd文件的字段是用冒号分开的。这个命令的输出就是所有用户名和对应的UID。
awk还能做条件筛选。比如从nginx访问日志里统计状态码分布:
awk '{print $9}' access.log | sort | uniq -c | sort -rn这条命令我几乎天天用。nginx日志默认用空格分隔,第9列是HTTP状态码,awk '{print $9}'把它提取出来,sort排序,uniq -c计数,再sort -rn按数量倒序排列。执行完就能看到200、404、500分别有多少次,接口异常一目了然。
awk本身是一门完整的编程语言,但对日常使用来说,掌握字段分割、print输出、简单条件判断就足够了。比如打印请求耗时大于3秒的日志行:
awk '$NF > 3 {print $0}' app.log$NF表示最后一个字段,{print $0}打印整行。可以把它理解成一个"按列组合的过滤器"。
3. 权限与用户管理:理解Linux安全模型,不要动不动chmod 777
3.1 权限位的底层逻辑:r、w、x对文件和目录含义完全不同
把权限位搞明白,是Linux从入门到进阶的一道分水岭。我见过太多人,遇到权限问题就chmod 777,这等于把门锁拆了,问题也确实消失了,但安全隐患留了一大堆。
权限用数字表示时,r=4、w=2、x=1,三组权限求和,就得到了常见的755、644、600这些数字。
关键在于:同样的r、w、x,作用在文件上和目录上,含义完全不同,很多人挂在这一点上。
对文件来说,r表示能查看文件内容,w表示能修改内容,x表示能当作程序执行。对目录来说,r表示能列出目录里有哪些文件名,w表示能在目录里创建、删除、重命名文件,x表示能进入这个目录(cd进去)。
这里藏着一个非常隐蔽的坑:如果一个目录只有w权限,没有x权限,你既进不去这个目录,也无法删除里面的文件。因为删除文件本质是修改目录的内容项,需要目录的写权限,而进入目录查找需要执行权限。所以给目录授权时要格外注意,目录的x权限相当于"通行证"。
对照表:
| 权限 | 对文件 | 对目录 |
|---|---|---|
| r(4) | 查看文件内容 | 列出目录中的文件名 |
| w(2) | 修改文件内容 | 创建/删除/重命名目录中的文件 |
| x(1) | 将文件作为程序执行 | 进入目录 |
3.2 chmod、chown:授出权限的正确姿势
理解了权限含义,再来看改权限的命令。chmod 755 file把文件权限设为属主可读可写可执行、属组和其他人可读可执行。现实中我推荐的安全习惯是:
- 普通配置文件:
644(属主可读写,其他人只读) - 可执行脚本或目录:
755(属主可读写执行,其他人可读执行) - 敏感文件(比如私钥、密码文件):
600(仅属主可读写)
给目录递归授权时用-R参数:
chmod -R 755 /data/web/但这里有个细节:如果目录下既有文件又有子目录,统一设成755会把文件也赋予执行权限,这倒不是致命问题,但不干净。更讲究的做法是用find区分处理:
find /data/web -type d -exec chmod 755 {} \; find /data/web -type f -exec chmod 644 {} \;这样目录统一755,文件统一644,既符合规范又能访问。
chown用来修改文件的属主和属组,格式为chown 用户:组 文件:
chown -R admin:admin /data/web/-R同样表示递归。我遇到过一种情况:网站文件明明是root所有的,运行Web服务的用户是www,结果www无法写缓存目录,页面一直报500。执行chown -R www:www /data/web/cache之后,问题立刻消失。所以部署应用时,第一件事就要确认目录的属主是不是运行进程的那个用户。
3.3 用户与用户组:useradd、usermod、passwd的实操要点
新建用户是每个Linux使用者都会碰到的基础操作,不同发行版的命令表现差异很大。CentOS(RHEL系列)里useradd和adduser是同一个命令;Debian/Ubuntu里adduser是更友好的交互式命令,会引导设置密码、创建家目录,而useradd默认行为反而不一样。
创建用户的推荐写法:
useradd -m -s /bin/bash zhangsan-m自动创建家目录/home/zhangsan,-s指定登录Shell为bash。如果不加-m,有些发行版生成的家目录可能不存在,用户登录后连工作目录都找不到,这是"用户建了却进不去"的常见原因。
把用户加入sudo组、获得管理员权限,不同系统写法不同:
# Debian/Ubuntu usermod -aG sudo zhangsan # CentOS/RHEL usermod -aG wheel zhangsan注意-aG里的-a是"追加"的意思,不加-a会把这个用户从原有的附加组里移除,只保留新加的组,这个坑我也踩过。
修改密码用passwd,自己改自己的密码直接执行passwd,root给指定用户重置密码执行passwd zhangsan。忘记密码时用root身份重置,不需要原密码。
4. 进程与系统状态排查:从"感觉卡"到"定位真凶"
4.1 ps与top:进程快照和实时状态怎么配合
系统变卡,第一反应就是看进程。ps是进程快照,top是实时刷新,两者互补。
ps aux是使用频率最高的组合。注意这里的aux不是某个参数,-ef是另一种等价写法。只看进程列表还不够,关键是看进程状态列STAT。看到R表示正在运行,S是睡眠(正常),Z是僵尸进程。僵尸进程是父进程没有正确回收子进程资源导致的,少量不用管,大量堆积就会耗尽系统资源,表现为PID持续增长、新进程起不来。
top打开后,默认按CPU使用率排序,按P键按CPU排序、按M键按内存排序,这两个键一定要记住。top顶部的load average有三个数字,分别代表1分钟、5分钟、15分钟的平均负载。判断负载高低有一个简单标准:数值持续大于CPU核心数就说明过载。
查看CPU核心数:
nproc比如CPU是4核,load average一直在4以上,说明排队等待的任务已经堆积,需要进一步确认是哪个进程吃掉了CPU。
4.2 kill的学问:kill -9不是万能钥匙
很多新手杀进程只会kill -9 PID,这是很危险的习惯。kill命令默认发送TERM信号(信号编号15),这是"请优雅退出"的意思,进程收到后可以清理临时文件、关闭句柄、保存数据再退出。而kill -9发送的是KILL信号,由内核直接强制杀死进程,进程没有任何机会做善后。
对数据库、Redis这类需要落盘的服务,直接kill -9可能导致数据文件损坏,恢复起来非常痛苦。
正确的杀进程顺序是:
# 先找到PID ps -ef | grep 服务名 # 或按进程名直接杀 pkill 服务名 # 等待几秒,如果进程还在,再用强杀 kill -9 PIDpkill按进程名匹配,比手动记PID方便。如果多个同名进程,或者命令行里带了特定参数,用pkill -f按完整命令行匹配:
pkill -f "python manage.py runserver"-f匹配的参数越多,误杀的概率越小。
4.3 磁盘、内存、负载:三个新手最容易误判的指标
df -h查磁盘空间,这个命令人人会。但磁盘还有一个隐性指标——inode。inode是文件系统存储文件元信息的结构,每个文件或目录都要占一个inode。当文件数量过多(比如缓存文件、小文件堆积),inode耗尽,磁盘明明还有空间,系统却报No space left on device,非常迷惑。
查inode使用率:
df -i看到IUse%接近100%,说明inode耗尽,需要清理大量小文件。
内存用free -h查看。很多人习惯盯着free看,发现空闲内存很少就以为内存不足。实际上Linux的内存管理会把空闲内存用作缓存(buff/cache),加速文件读写,这些内存在程序需要时可以释放出来。所以看内存要用available字段,它才是真正可用的内存量。
排查系统整体压力时,vmstat是个好帮手:
vmstat 1 5每秒打印一次,共5次。重点看r列(运行队列,超过CPU核数说明CPU繁忙)、si和so列(swap换入换出,持续大于0说明内存不足,系统在疯狂使用交换分区)。这块判断内存还是磁盘瓶颈时很有用。
5. 网络排查常用命令:从连通性到接口健康的检查顺序
5.1 ping、telnet、nc:网络到底通不通
排查网络问题时,我的习惯是从底层往上层逐层检查。
ping测试IP层的连通性,ping -c 4 目标IP指定发送4个包。但ping通只能说明ICMP可达,不代表目标端口开放、服务正常。接下来要测TCP层的连通性。
传统方式用telnet 目标IP 端口,能连上会显示Connected to,连不上就一直卡着直到超时。但telnet测试有个缺点,没有明确的退出码,在脚本里判断麻烦。更推荐用nc(netcat):
nc -zv 192.168.1.100 3306-z表示只扫描不发送数据,-v输出详细信息,-w 3设置超时时间3秒。端口开着会返回open,关闭会返回Connection refused。这个命令在脚本里也很好用,根据退出码判断端口状态。
5.2 ss与netstat:查看端口监听和连接状态
端口测通了,接下来要看本机的端口监听状态。netstat -tlnp是经典命令,ss -tlnp是新一代替代品,输出更快更准,在排查大量连接时尤其明显。
ss -tlnp参数含义:-t只看TCP,-l只看监听状态的端口,-n不解析主机名和端口名显示数字,-p显示占用端口的进程PID和名称。这个命令解决的核心问题是:"这个端口到底被谁占着"。比如启动服务时提示Address already in use,执行一下就知道是什么进程占用了。
Linux下TCP连接状态中还经常看到大量TIME_WAIT和CLOSE_WAIT。用ss -s快速看连接状态统计:
ss -sTIME_WAIT多一般不用操心,这是TCP主动关闭连接后的正常状态,过一段时间会自动消失。但CLOSE_WAIT多就要警惕了,它通常表示程序收到对端关闭连接请求后,自身没有正确调用close关闭连接,属于代码层面的连接泄漏。这时候就别折腾系统参数了,得从业务代码下手。
5.3 curl:接口自测和故障复现的必备工具
排查Web服务的请求问题,curl是我的首选。它能模拟HTTP请求,把整个交互过程打出来。
最基本的几个用法:
curl -I https://example.com-I只获取响应头,200还是404一眼看清。-v输出更详细的交互过程,包括DNS解析、SSL握手、请求头、响应头,排查接口突然不通时非常有用。
判断一个接口的健康状态,我常用这套组合:
curl -s -o /dev/null -w "HTTP状态码: %{http_code} 耗时: %{time_total}s\n" https://example.com/api/health-s静默模式不显示进度条,-o /dev/null把响应体丢弃,-w输出自定义信息。执行后直接看到HTTP状态码和总耗时,比打开浏览器访问、肉眼观察快了不知道多少倍。配合while循环还能做简单的接口压测和可用性监控。
POST接口的测试需要带数据:
curl -X POST -H "Content-Type: application/json" -d '{"name":"test"}' https://example.com/api-X指定请求方法,-H添加请求头,-d携带请求体。日常联调、复现线上接口问题,这一套基本够了。
6. 归档压缩与跨机器传输:tar、zip、scp、rsync的取舍
6.1 tar:参数组合不要死记,按含义理解
tar是Linux下最常用的归档工具。多数人记tar -czvf和tar -xzvf是死记的,换个需求就懵了。其实每个字母含义很清晰:
c:创建归档x:解压归档z:通过gzip压缩/解压v:显示处理过程f:指定归档文件名(后面必须跟文件名,所以f永远放在参数最后)C:解压到指定目录
创建压缩包:
tar -czvf backup.tar.gz /data/www解压到当前目录还是指定目录:
tar -xzvf backup.tar.gz tar -xzvf backup.tar.gz -C /target/dir注意-C指定解压目标目录,这个目录必须提前存在。不解压直接查看压缩包内容:
tar -tzvf backup.tar.gz这里把c换成t表示"列出内容"。
热搜里频繁出现的"linux解压文件乱码",多半发生在zip格式的压缩包上,tar.gz格式本身没有乱码问题,因为tar保留了文件名的原始字节,没有额外的编码转换。如果拿到的是zip包而且是从Windows压过来的,见下面一节。
6.2 zip与unzip:跨平台传输的编码细节
zip格式在Windows和Linux之间传输,乱码是经典老大难问题。根源在于Windows默认用GBK编码保存文件名,而Linux默认用UTF-8,解压时按UTF-8解析GBK编码的文件名,自然全是乱码。
解决方式是用unzip指定编码:
unzip -O CP936 archive.zip-O参数指定解压时的字符编码,CP936就是GBK。这样解压出来的文件名基本能正常显示。不是所有版本的unzip都支持-O参数,Debian/Ubuntu下的unzip通常可以,如果提示参数错误,可以考虑安装unar代替,它对编码的处理更省心。
压缩时为了避免乱码传播,我在Linux下对目录打包时,优先用tar.gz,不用zip。zip虽然和Windows兼容性最好,但编码问题太容易踩坑,能用tar就用tar。
6.3 scp与rsync:简单复制和增量同步怎么选
服务器之间传文件,scp是最简单直接的方式:
scp /data/app.tar.gz user@目标IP:/data/ scp -r /data/www user@目标IP:/data/-r递归复制整个目录。scp基于SSH协议,安全方面不用担心,但它的逻辑是"全量复制",每次传整个文件,同一个文件第二天再传还是全量,效率不高。
做周期性、重复性的同步时,用rsync,它只传输差异部分:
rsync -avz /data/www/ user@目标IP:/data/www/参数含义:-a归档模式,保留权限、时间戳、属主等属性;-v显示过程;-z传输时压缩数据。第一次执行是全量同步,第二次只传变化的部分,这在日志备份、代码发布时效率优势非常明显。配合crontab,还能实现简单的定时同步。
这里有一个我踩过的坑:rsync源路径末尾的斜杠有讲究。rsync -avz /data/www/ ...表示同步目录里的内容;rsync -avz /data/www ...表示同步这个目录本身。也就是说,带斜杠会在目标目录里直接铺开文件,不带斜杠会在目标目录里先建一层www目录。中间部署脚本时因为斜杠问题,文件层级多套了一层,排查半天才意识到是路径末尾的斜杠差异。
跨机器传输时,另一个实用命令是rsync配合--delete参数,让目标目录严格和源目录保持一致,源目录删除的文件,目标目录也一并删除。但--delete有风险,建议先加--dry-run试运行,查看会删除哪些文件,再真正执行。
做运维这行,命令记不全很正常,man手册永远在那里。真正拉开差距的不是背了多少命令,而是知道在什么场景下该用哪条命令、输出结果怎么解读、有哪些隐含的坑。上面这些命令和习惯,是我从踩坑中学到的最实用的部分,你可以按这个思路,把每一条命令都敲一遍,再想一想它在你自己的项目里能解决什么问题,比单纯收藏一份大全有效得多。