没用过Linux的人,总觉得命令行是“大佬的玩具”。可真在服务器上干过几年活儿,你会发现命令行才是效率和掌控感的来源。Linux命令难吗?难,但难的不是记不住参数,而是没搞懂命令背后“一切皆文件、单点组合、输入输出流转”这套设计思路。所以这篇文章不讲大而全的Linux命令手册,而是以一个常年在生产环境摸爬滚打的工程师视角,把Linux命令及使用方法拆成三块:先聊怎么搭建命令的思考框架,再讲高频命令的使用细节,最后分享一堆踩坑和排查经验。无论你是刚接触Linux的新手,还是在用Mac、Windows上装了WSL的老人,读完这套方法,至少能让你在命令行里少走半年弯路。
1. 先建立命令的思维框架,而不是背命令
很多人学Linux命令,上来就找一张“命令大全”存到书签里,然后就没有然后了。我刚开始也是这样,ls、cd、mkdir会用了,就觉得自己会了。可一碰上排查线上问题,手就停在键盘上任凭满屏日志从眼前刷过,完全不知道下一步该敲哪条命令。后来我才想明白一件事:Linux命令本质上是几百个独立的小程序,你需要的不是记住它们,而是理解它们之间是如何被组合成一个完整系统流程的。
1.1 命令的本质:参数、标准输入输出、管道
Linux命令运行起来以后,其实就三件事:读入数据、处理数据、输出数据。绝大多数命令默认从标准输入读,往标准输出写,错误单独走标准错误。这设计听起来简单,但它带来的组合能力是爆炸性的。
举一个最典型的例子:cat error.log | grep "timeout" | sort | uniq -c | sort -rn | head -20。如果看不懂这一串,那说明你还没把“管道”这个灵魂概念刻进脑子里。管道符|把前一条命令的标准输出接到后一条命令的标准输入,数据就像水流过一根根管子。这时候你不需要把日志拷贝到本地再用IDE分析,直接在终端里就能完成一次轻量级的数据流水线。
这个设计最大的价值是:让每一条命令都保持“单一职责”。cat只负责把文件内容塞给输出,grep只负责过滤,sort只负责排序,uniq只负责去重统计。没有任何一条命令需要替你完成全流程,你只要把它们像乐高一样拼起来。我经常跟带的新人说一句话:你每记住一个命令的“输入输出约定”,就等于多了一块乐高积木,之后拼解决方案的速度会指数上升。
1.2 用“最小可用清单”替代“大而全手册”
市面上各种命令大全列了五六百条命令,说实话,日常业务开发用到的可能就三十多条。与其海量背诵,不如先搭一个“最小可用清单”,把每类场景里最常用的一两条命令练熟。我自己的清单大概是这样的:
- 文件目录:
ls、cd、find、du、df - 查看文件内容:
cat、less、head、tail、grep - 文本处理:
awk、sed、sort、uniq、cut - 进程系统:
ps、top、kill、systemctl - 网络排查:
ping、curl、ss、telnet、nc - 权限管理:
chmod、chown、sudo、useradd
这三十多条命令,每条花十分钟把man手册的常用参数过一遍,再上手敲一遍,基本就能覆盖90%的日常场景。剩下那些不常用的命令,等真遇到问题的时候再针对性查man或者help,效率反而更高。别让工具的学习成本淹没问题本身,这才是你该有的效率观。
2. 日常文件与目录操作,别忽视那些“看似简单”的命令
文件操作是Linux最基础的一层,但恰恰是这层,藏着太多人用了多年都没注意到的细节。这些细节不解决,你也能干活儿,但就是慢;解决了以后,你会发现同样是操作文件,别人折腾五分钟,你一条命令秒完。
2.1 ls、cd、find:从“会敲”到“用得漂亮”
先说ls。新手都会ls -l,但生产环境里我几乎很少用裸的ls -l,因为输出的体积信息对人类不友好。我更常用的是ls -lh,加一个h(human readable)参数,文件大小会显示成4.0K、234M这种直观格式。还需要按时间排序找最新文件时,用ls -lt,配合head -5就能立刻看到最近改动的那几个文件。另外,那些隐藏文件(比如.gitignore、.env)要用ls -a才能显示,我见过不止一个同事因为没看到隐藏文件,处理配置时一脸茫然。
cd就更值得说了。cd -这个神技能,能在当前目录和上一次目录之间来回跳,是我在多个项目目录之间切换时最喜欢用的命令。还有人不知道pushd和popd,配合dirs可以维护一个目录栈,在几个工作目录之间来回往返,再也不用一遍遍敲相对路径。真要经常跑某些固定路径,给~/.bashrc里写几个alias,比如alias goto-project='cd /opt/workspace/project',省下来的时间非常可观。
find是很多人觉得“难”的命令,因为它的参数比ls多得多。但你要记住它的核心心智模型:find就是按条件在指定目录树下“扫描”文件。我平时最常用的是三种:
find /data/logs -name "*.log" -mtime -7,查找最近七天内修改过的日志文件;find /opt -type f -size +500M,找出超过500MB的大文件,这在排查磁盘占满时极其有用;find . -name "*.py" | xargs grep "重要线索",在所有Python文件里搜索某个关键词,比一个个文件打开看高效太多。
还有一个细节:find默认会进入所有子目录,如果目录层级特别深,扫描会慢。可以用-maxdepth 2限制层级数,只扫两两层,速度能快一个量级。排查问题时,“范围越小、速度越快”是铁律。
2.2 cat、tail、less:查看文件别只会用cat
很多人查看文件就是cat一把梭。文件短还好,文件一长,整个终端被刷屏,还得往上翻,效率极低。我自己对查看文件类命令的使用原则是这样的:小文件用cat,大文件用less,动态日志用tail -f。
less这个命令值得单独练一下。它打开大文件是“按需加载”,不会一次性把整个文件读进内存,所以打开几百MB的日志也不会卡死。进入less之后,按/可以搜索关键词,按n跳下一个匹配项,按G跳到文件末尾,按g跳到开头。很多人不知道的是,less还可以直接打开一个正在写入的日志文件并实时查看,效果类似tail -f,但搜索等功能更顺手。
tail -f更是排查线上问题的利器。比如Java应用打印的日志文件,在排查死循环或者OOM时,直接tail -f app.log挂着,然后去触发一个请求,日志实时滚出来,问题链路一目了然。tail -n 200可以显示最后200行,比慢慢翻屏幕强得多。还有tail -f配合grep的用法,tail -f app.log | grep "ERROR",只把错误级别的日志流出来,终端立刻清爽很多。
注意:
tail -f不会自动退出,要退出就按Ctrl + C。如果只想看文件末尾追加的内容然后退出,用tail -F在某些场景下更合适,但常规情况下-f足够。
2.3 du、df:磁盘到底被谁吃掉了
磁盘满了,第一反应别去用ls瞎翻,系统提供了两个专门命令:df和du。df -h查看整个文件系统的使用率,一秒钟定位到哪个挂载点满了;du才是真正站在业务视角计算目录占用大小的工具。
我最常用的排查组合是:
df -h du -sh /opt/* | sort -hr | head -10先看是否有分区爆掉,然后直接对/opt下的各个子目录做汇总排序,最大的那个目录立刻浮出水面。进一步深入时用du -h --max-depth=1 /opt/某个大目录 | sort -hr,一层一层往下拆,直到找到那个吃磁盘的文件或者日志。这个组合拳帮我快速定位过很多次“日志越滚越大”的故障。
这里有个坑要提醒:du统计的是文件占用的数据块大小,不是ls里看到的逻辑文件大小。对于稀疏文件或者被删除但仍被进程占用的文件,du和ls的结果可能对不上。如果你发现磁盘明明满了,可是du统计下来却对不上账,多半是有某个进程还持有着已删除文件,用lsof | grep deleted能找出来,这个后面会细说。
3. 文本处理与数据流:命令行真正的“高光时刻”
如果你只会查看文件,那Linux命令对你来说还只是“高级记事本”。真正让命令行封神的,是它对文本流的处理能力。日志分析、数据统计、配置批量替换,这些活儿拿到命令行里,往往就是三五行管道命令的事。而这套能力的核心,就是grep、awk、sed这三驾马车。
3.1 grep精读:过滤只是入门,上下文才是关键
grep名字来源于“全局正则表达式打印”,它的核心能力是“按模式过滤文本行”。但我发现很多人除了grep 关键词 文件之外,对它的其他参数一无所知。
在实际排查中,grep最实用的参数是上下文参数。grep -n -C 5 "Exception" app.log,-n输出行号,-C 5显示匹配行的前5行和后5行。这个用法让你看到异常抛出的前后文,而不是孤单的一行报错信息,定位能力会有一个质的提升。-A 3只显示后3行,-B 3只显示前3行,按需要选择。
grep还支持用正则过滤复杂模式。排查IP地址段,用grep -E "192\.168\.1\.[0-9]{1,3}";匹配多个关键词任意一个,用grep -E "timeout|refused";多个关键词全部命中,用grep "keyword1" file | grep "keyword2"两级过滤。grep -v是反选,剔除某个关键词,grep -o则只输出匹配的部分而不是整行,这在提取日志中的IP、订单号时非常节省精力。
3.2 awk:不是“装逼工具”,是字段提取神器
初次见到awk的人都有点劝退,因为它长得不像普通命令,语法更像一个小型编程语言。但你只要记住它的核心:awk把每一行按分隔符拆成多个字段,然后可以对这些字段做过滤、计算、格式化输出。这个能力在做日志分析时几乎无可替代。
最经典的入门例子:awk '{print $1, $4}' access.log。默认以空格为分隔符,$1是第一列,$4是第四列,一行就把日志里的关键字段摘出来了。配合日志格式稍微复杂的情况,可用-F指定分隔符,比如awk -F',' '{print $2}'处理CSV格式。
awk真正好用的是数值聚合。比如统计日志里各接口被请求了多少次,可以这样:
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20$7取出请求路径,sort排序,uniq -c统计次数,sort -rn按次数倒序排列,head -20看Top20。这一串不到五十个字符,就把“哪些接口是热点”这个问题回答了。再用awk算平均耗时也一样简单,awk '{sum += $NF; count++} END {print sum/count}',两行逻辑搞定脚本语言几十行的活。
不要怕awk语法,你只需要掌握:BEGIN块(处理前执行)、主循环块(逐行处理)、END块(处理完后执行)、变量与
printf。这一套就够日常用了,此后每多看一眼手册,你的文本处理能力就涨一分。
3.3 sed:批量替换,别再用编辑器一个个改了
s/in/out/g是sed最出圈的用法,它的本质是“流编辑器”,逐行读取、逐行处理、逐行输出。最常见的替换场景是:sed -i 's/old_text/new_text/g' config.properties。加-i才是真正改写文件,不加的话只是把替换后的内容打印到屏幕,不会动原文件。我第一次用sed替换配置文件时忘了加-i,结果屏幕上看着替换成功了,实际上文件纹丝不动,折腾了半天才发现问题。
除了替换,sed还可以做“只输出某几行”这种操作:sed -n '100,200p' app.log,查看第100行到第200行的区间内容。这个配合前面说的less和tail,基本覆盖了“按行查文件”的所有姿势。sed还能做插入、删除,比如sed -i '/debug/d' file删除包含debug的行。注意-i是直接改文件,建议操作前先备份或者用Git管理文件,否则一条命令把几百行配置全替换错了,想恢复都难。
3.4 管道组合拳:一次真实的日志分析实战
文本处理命令单独用只是皮毛,组合起来才会让你惊呼。我记得有一次生产环境报接口响应变慢,我拿到的是一个1.2GB的网关日志。常规编辑器想打开都费劲,我用三分钟跑了一组命令就把问题定位了:
grep "接口A" access.log | awk -F',' '{print $(NF-1)}' | sort -n | tail -30取出那个接口的耗时字段,把所有耗时排序后看最大值,发现最慢的几次耗时竟然是正常值的几十倍。接着再用grep -C 20 "接口A" access.log | grep -E "timeout|retry" | head -50看慢请求附近的日志,很快发现是下游某个服务出现了连接超时重试导致的连锁反应。整个过程没导出任何数据,全部在终端完成。
这套组合拳的前提,就是你清楚每条命令的输入输出约定,并且知道怎么用管道串起来。在Linux命令行里,组合不是高级技巧,而是基本功。
4. 进程、网络与系统状态:线上排查必备三板斧
文件操作和文本处理管好了“静态的数据”,但线上问题多数发生在“动态的进程”和“流动的网络”上。这一块是Linux命令综合能力的终极大考,也是区分“会用Linux”和“真会Linux”的分水岭。
4.1 ps、top、kill:把进程状态看穿
ps -ef和ps aux是我最常用的两条进程查看命令。-ef偏向完整进程信息,aux会额外显示CPU和内存占用率。很多人会用ps aux | grep java来找特定进程,但这里有个经典坑:grep java会把自己这条命令也匹配进去,因为命令行里本身就包含“java”字符串。规避方法是在grep条件里加一个方括号,比如ps aux | grep [j]ava,这样就不会匹配到grep本身,输出干净很多。
top是看实时资源的工具,进入交互界面后,按P按CPU排序,按M按内存排序,按1看每个CPU核的使用率。如果嫌top的交互界面不利于脚本处理或者远程操作,还可以用top -b -n 1 | head -30输出一波快照后退出。生产环境更推荐用top -b -n 1配合head看头部信息,不阻塞终端。
kill也不是只有kill -9一种姿势。我最常用的反而是kill默认的“优雅终止”,它向进程发送SIGTERM,让进程有机会做清理工作再退出。只有进程卡死不响应时,才考虑kill -9强制杀死。动不动就kill -9杀掉Java进程,很可能导致堆内存没有触发清理、临时文件残留、Eureka心跳来不及注销等问题,这习惯一定要改。
4.2 端口、连接与网络连通性排查
排查网络问题时,其实很讲究“先连通、后细节”。第一步先确认网络通不通,ping看一眼延迟和丢包;第二步确认端口通不通,用telnet 目标IP 端口试一把,通的话会显示Connected to,不通就会卡住或者直接Connection refused;第三步才是用ss或curl看细节。
很多人对netstat很熟,但生产环境里我更喜欢用ss,它比netstat输出更快、信息更准确。判断“谁在监听这个端口”最简单的方式是:ss -lntp | grep 8080,-l只看监听状态的连接,-n显示数值端口,-t只显TCP,-p显示进程和PID。如果加上-a可以查看所有连接,包括ESTABLISHED、TIME_WAIT等状态的连接,排查大量连接堆积时非常关键。
还有一个易被忽略的命令是lsof。它能让“某个文件被哪个进程占用”这种问题一秒钟有答案。配合磁盘占满场景,lsof | grep deleted能查到已经被删除但仍被进程占用、导致磁盘空间无法释放的文件,这种问题用du是查不出来的。杀进程前先lsof -i:端口确认是谁在占坑,比直接kill盲猜靠谱一万倍。
4.3 systemctl与服务管理:别用“杀进程”代替“管服务”
在Linux下通过systemd跑服务,已经不推荐直接执行二进制文件来启动了,而是应该与服务管理器打交道。systemctl status 服务名看运行状态,systemctl restart 服务名重启服务,systemctl enable 服务名设置开机自启,systemctl logs -u 服务名查看启动日志。这套机制胜在统一了服务的启动、停止、重启、开机自启等行为,也让服务意外退出后可以被自动拉起。
有个排查经验:服务起不来时别全靠systemctl start返回的提示,很多情况下真正的报错藏在journalctl -u 服务名 -n 50里。比如启动脚本里路径写错、依赖的端口被占用、配置文件语法错误,这些在journal里通常有直接的原因。省去自己瞎猜的时间,一次定位。
5. 权限、用户与安全基础:管住“谁能碰文件”
我接手过几次线上事故复盘,其中有两三次的根因就出在权限配置不当。要么是进程以root身份运行,被攻破后整个机器裸奔;要么是配置文件权限过宽,不该读的人全都能读。所以权限这块,是我认为Linux命令里最需要“认真对待”的部分。
5.1 看懂文件的权限面孔:r、w、x的三个维度
Linux的权限模型说简单很简单,就是“用户、组、其他人”三个维度再乘上“读、写、执行”三种权限。ls -l输出第一列的-rwxr-xr--,第一个字符是文件类型,剩下九个字符分成三组,每组三个权限位。我见过太多人看到这串字符就发怵,其实拆开理解后,它就是三个字母的排列组合。
权限的数字表示法是另一层常见操作。r=4、w=2、x=1,把三个数相加得到一个数字,比如rwxr-xr--就是755。chmod 755 script.sh的意思是:文件所有者有全部权限,同组用户和其他用户只有读和执行权限。这个数字思维比字母直观很多,计算起来也快。
注意:不要给脚本或者二进制文件随便加执行权限,更不要给所有文件统一
chmod 777。777意味着所有用户可读可写可执行,等于把服务器的大门钥匙复制给所有人。我曾经在一次安全扫描时发现项目里有人为了省事,把配置文件chmod 777了,这要是被扫出来,妥妥的高危风险。
5.2 chown、chmod、sudo:用对人,分好组
改文件所有者用chown。比如把某个应用目录从root移交到应用账号:chown -R appuser:appgroup /opt/app,-R递归处理子目录。如果忘了改所有者,用应用账号启动服务时就会看到Permission denied,这个报错在启动脚本里非常常见,八成是目录属主不对。
sudo属于“临时提权”工具,它解决的场景是:普通用户平时不持有root权限,遇到管理操作时用sudo临时获得授权,同时所有sudo操作都会被记录到日志中。我个人的建议是:日常操作尽量用普通账号,需要管理时才sudo,养成这个习惯能避免很多“手滑毁所有”的事故。毕竟在root权限下,rm -rf /和rm -rf /var之间,可能就差一个空格的距离,而这个空格造成的后果是天文数字。
实际工作中还有一个高频场景是给账号添加公钥实现免密登录,这涉及ssh-keygen、authorized_keys、文件权限配合。这里有个经典的坑:authorized_keys文件的权限必须是600,.ssh目录权限必须是700,否则登录会被拒。这个细节让我在客户现场排查过无数次“明明密钥没问题,就是连不上”的问题。
6. 常见问题与排查技巧实录
这部分是硬核经验的沉淀。每一条都是我在生产环境里碰到过、然后记忆深刻的问题。整理成速查表,方便你遇到时能快速对照。
6.1 命令找不到,报“command not found”
这种情况多半是环境变量PATH没配好。比如下载了某个二进制工具放在/opt/bin下,执行时却提示找不到。解决方法有两个:一是直接使用绝对路径/opt/bin/工具名;二是把它加入PATH,在~/.bashrc里加一行export PATH=$PATH:/opt/bin。这里要提醒,改完~/.bashrc后记得执行source ~/.bashrc或者重新登录终端,否则不生效。还有一种情况是工具本身没安装,直接apt install或者yum install装上即可。
6.2 磁盘明明满了,却找不到是谁占的
前面提过lsof | grep deleted,这里展开说一下。曾有一次客户反馈测试环境磁盘告警,我用df -h看到根分区100%,然后du -sh /*把根目录下一层层往里查,所有目录加起来却远小于总量。后来突然想到被删除但是被进程锁定的文件,执行lsof | grep deleted,果然发现一个Java进程把1.8GB的日志文件删掉了但还在写。进程持有的文件删除后,空间并不会立马释放,直到进程退出或者重启。这种问题的正确解法是重启对应服务,而不是傻傻删除其他日志文件。
6.3 kill不掉进程,或者端口明明没监听却提示被占用
kill -9杀不掉的进程,多半是处于不可中断睡眠状态,比如正在等待磁盘I/O。这种情况只能用ps查看进程状态列,确认是不是D状态,等待I/O恢复后再kill。如果端口提示被占用,但ss -lntp列出的进程对不上,很可能是被容器或者Docker映射占用了,这时候要去检查容器端口映射。另外,TIME_WAIT状态的大量连接,也会让端口看起来被占用,但它们过一会儿会自动消失,不用惊慌。
6.4 线上不准乱动,先备份再操作
这不算一条命令,而是我最后想压轴强调的习惯。高危命令执行前先备份:cp config.properties config.properties.bak或者tar czf backup.tgz /opt/app。改了配置文件、启停服务、调整权限这些操作,永远先确认再动手。因为命令行是“即时生效”的,没有像图形界面那种二次确认弹窗,一条rm -rf下去可能连后悔的机会都没有。这个习惯救过我无数次,希望它也能救你。
如果说有什么是我在实际操作中最深的体会,那就是Linux命令不是靠背出来的,而是靠“遇到问题—拆解问题—组合命令—验证结果”这个循环练出来的。每解决一次线上的真实问题,你掌握的命令就会多一层理解,命令行在你心里的形象也会从一堆碎片变成一张网络。别指望一天练就全能,先从今天说的这套逻辑出发,把日常操作里用到的每条命令都问一句“它为什么这么设计”,你会在某个时间点突然发现,自己已经能在命令行里游刃有余了。