研一开学第二周,师兄扔给我一个服务器账号,说数据在 /data 下面,你先跑个 baseline。
我当时点头点得特别果断。
然后我在那台机器前坐了三个小时,什么都没跑起来。
不是代码写不出来,是我压根不知道自己在哪。屏幕上就一行光标闪着,我连怎么确认当前目录都要现搜。中间我误删了一个文件,也不知道找谁认领;我改完 .bashrc 保存退出,环境还是老样子;最后我实在扛不住,去问师兄。
他没笑我,就走过来敲了四个命令,问题解决了。
pwd、ls -la、which python、echo $PATH。
四个。加起来不到三十个字符。
那天我意识到一件事:我不是不会用 Linux,我是脑子里没有一张关于这台机器的地图。
后面两年多我在服务器上熬了无数个夜,回头看,学命令行这件事我走过的弯路挺典型的,也总结出了一些确实有用的东西。这篇就把它讲清楚,尽量不讲空话。
一、先把最大的误区拆掉:命令行不是知识,不该拿来背
我刚开始学的时候干了一件特别愚蠢的事。
我找了一份 Linux 常用命令一百条的清单,打印出来,贴在显示器旁边。
三个月后我撕了它。
因为那张纸上的命令,一半我从来没用过一次,另一半我天天用,用得根本不需要看纸。
这就是问题所在。命令行的能力不是靠记忆量堆出来的,它更接近骑车和打字。你不是靠背下来的,你是靠在具体麻烦里用出来的。
我的判断是,很多人学不下去,就是因为一开始就选错了模式。
背清单的模式有三个致命伤。
第一,没有场景,记不住。你今天背了 du,如果一个月内没遇到磁盘满,你一定会忘。
第二,没有痛感,理解不深。我第一次真正搞懂 du 和 df 的区别,不是看教程,是磁盘满了、我找了一下午没找到大文件在哪。
第三,最要命的,背命令给不了你排查能力。真实场景里没人告诉你该用哪个命令,你面对的只是一句「它跑不了」。
所以正确的入门姿势不是背命令,是先在脑子里装几个心智模型,让你看到陌生命令不慌,看到报错知道往哪看。
下面这一节是我觉得整篇最值钱的部分。
二、四个心智模型,比一百条命令有用
模型一:所有命令的结构都是同一套
绝大多数命令长这样:
命令名 选项 参数
ls -lh /data
ls 是命令,-lh 是选项,/data 是参数。
这里有几个规律,理解了以后你看任何陌生命令都不会懵。
单横线加单字母是短选项,可以合并。-l -h 等于 -lh。
双横线加单词是长选项,一般不能合并。--help、--recursive。
同一个字母在不同命令里可能完全不同。-r 在 cp 里是递归,在 sort 里是反向。所以不要试图记「-r 是什么意思」,要记「这个命令的 -r 是什么意思」。
有些选项后面要跟值。-n 1、--name test。
这个规律很朴素,但它带来的效果是:你看到 rsync -avzP src/ dst/ 的时候,不会觉得它是一串咒语,你知道那是四个开关和两个路径。
模型二:一切都是文本流,而且有三条通道
这个是理解命令行的分水岭。
每个命令都有三条通道:
标准输入,编号 0,数据从哪进来。 标准输出,编号 1,正常结果往哪出。 标准错误,编号 2,报错往哪出。
默认情况下,1 和 2 都打到你的屏幕上,所以看起来是一回事。它们不是一回事。
这就解释了一个新手极其常见的困惑。
你跑了这么一条:
python train.py > log.txt
然后你发现报错还在屏幕上刷,log.txt 里干干净净。
因为 > 只重定向了 1 号通道,报错走的是 2 号。
正确写法是把两条通道合起来:
python train.py > log.txt 2>&1
2>&1 的意思是把 2 号通道指向 1 号通道现在的地方。
顺手把重定向符号一次说清楚:
> 覆盖写入,原文件内容直接没了。 >> 追加写入,接在后面。 2> 只存报错。 &> 全部存进去,是上面那种写法的简写。 /dev/null 是黑洞,2> /dev/null 表示报错我不看了。
还有一个我用得非常频繁的:
python train.py 2>&1 | tee log.txt
tee 的作用是既打到屏幕,又存进文件。跑长任务的时候特别舒服,你能实时看,也能事后翻。
这一小节我建议真正动手试一遍,试完你对命令行的理解会上一个台阶。
模型三:管道,也就是 Unix 的核心哲学
Unix 的设计思路是:每个工具只做一件小事,做好,然后靠管道拼起来。
| 的意思就是把左边命令的输出,塞给右边命令当输入。
我举一个能把这个思想讲透的例子。假设你有一份访问日志,你想知道哪些 IP 触发 404 最多。
grep " 404 " access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
一步一步看:
grep " 404 " 挑出含 404 的行。 awk '{print $1}' 只取每行第一列,也就是 IP。 sort 排序。 uniq -c 统计相邻重复行的数量。 sort -rn 按数字倒序排。 head -10 取前十条。
有意思的是,这里为什么必须先 sort 再 uniq?
因为 uniq 只能识别相邻的重复行,它不会全局去重。这是新手最容易踩的一个坑,写成 uniq -c | sort 结果就完全不对。
这一串六个命令,没有一个是复杂的,但组合起来,它替代了一个你可能要写二十行 Python 的脚本。
这就是命令行真正强的地方。它不是给你一堆功能,它给你一套可以任意拼接的积木。
所以学命令行,sort、uniq、wc、cut、awk、xargs、head、tail 这几个拼接件的价值,远远高于那些看起来很酷的单一命令。
模型四:文件树、路径和权限
文件系统是一棵树,/ 是根。
~ 是你的家目录。 . 是当前目录。 .. 是上一层。 - 在 cd - 里表示上一个待过的目录,这个小技巧在两个目录之间来回跳的时候很省事。
绝对路径从 / 开头,跟你现在在哪无关。相对路径不带头,跟你现在在哪相关。
这个区别在写脚本的时候会咬人。你在脚本里写相对路径,别人从另一个目录调用你的脚本,就崩了。
然后是权限。ls -l 出来那一串 drwxr-xr-x,很多人看了两年也没搞懂。
其实很简单。
第一位是类型,d 是目录,- 是普通文件,l 是链接。
后面九位分三组,分别是所有者、同组用户、其他人。每组三位是读、写、执行。
数字表示法就是 读 4、写 2、执行 1,加起来。
755 就是所有者 4+2+1 全给,其他人 4+1,能读能进不能改。 644 是常见的文件权限,自己可读写,别人只读。
这里有个概念要单独强调,因为它绕过很多人:目录上的 x 权限,不是「能执行这个目录」,是「能进入这个目录」。
所以一个目录如果有 r 没有 x,你能看到里面有什么名字,但进不去。这种诡异状态在共享服务器上真的会遇到。
三、环境变量:新手八成的玄学问题都在这里
我敢说,实验室里新同学问我的问题,有一半最后都指向环境变量。
典型症状是这些:
我明明装了这个包,为什么找不到。 我明明创建了 conda 环境,为什么用的还是系统 Python。 这个命令我昨天还能用,今天怎么没了。 我改了配置文件,为什么没生效。
这几个问题背后是同一件事:你以为你在用 A,其实系统给你的是 B。
排查它只需要两个命令。
which python echo $PATH
which 告诉你,你现在敲的这个命令,实际执行的是哪个文件。
$PATH 是一串用冒号分隔的目录。你敲任何命令,系统就按这个顺序在这些目录里找,找到第一个就用,后面的不管了。
所以「找不到命令」的意思其实是:这个程序不在 $PATH 列的那些目录里。而「用错了版本」的意思是:有个你不想要的版本,排在你想要的那个前面。
理解了这一点,环境问题就从玄学变成了可以查的东西。
再说配置文件为什么不生效。
export PATH=xxx 这种写法只在当前这个终端窗口有效。你关掉窗口,一切归零。
想让它长期生效,得写进配置文件。但配置文件也有讲究:
.bashrc 在每次开一个交互式 bash 的时候执行。 .bash_profile 或 .profile 在登录的时候执行。 用 zsh 的话对应的是 .zshrc。
坑在于,你 ssh 登录服务器和你在服务器上新开一个 shell,走的路径可能不一样。所以有时候你会遇到「本地能跑,提交到集群就说找不到命令」。
改完配置文件记得让它立即生效:
source ~/.bashrc
source 的意思是在当前 shell 里执行这个文件,而不是开一个新进程去执行。这个区别也很重要,你直接 bash ~/.bashrc 是没用的,因为改动发生在子进程里,子进程一退出就没了。
这一段有点抽象,但它是真正能让你少熬几个夜的东西。
四、退出码和短路:命令行开始有逻辑了
每个命令跑完都会留一个退出码。0 表示成功,非 0 表示失败。
echo $?
这个命令看的就是上一条命令的退出码。
基于这个,有两个连接符:
&& 前面成功了才跑后面。 || 前面失败了才跑后面。
实际用起来是这样:
mkdir -p output && python train.py --out output
目录建好了才开始训练。如果建目录都失败了,就别浪费时间了。
python train.py || echo "训练挂了" >> fail.log
失败才记一笔。
还有个 ;,不管成功失败都往下走。
区别很关键。我见过有人写 cd /some/dir; rm -rf *,如果 cd 失败了,rm 就在原地执行了。这种写法真的会出人命,必须用 &&。
顺便说 mkdir -p 的 -p:目录已存在也不报错,父目录不存在会一路建上去。写脚本的时候基本是标配。
五、学习顺序:按你的麻烦学,不要按字母表学
我不建议任何人从 A 到 Z 地学命令。我建议按你实际会遇到的麻烦,分层推进。
第一层,我在哪,这有什么
pwd、cd、ls、cat、less、head、tail
只说两个细节。
大文件别 cat,会把终端刷爆,用 less,上下箭头翻,/ 搜索,q 退出。
tail -f 是跟踪日志实时输出,做实验的人一天要用几十次。
第二层,我要找东西
grep、find、which
grep -rni "关键词" . 是我用得最顺的一串:递归、显示行号、忽略大小写。接手一份不是自己写的代码时,这个比在编辑器里点来点去快得多。
如果服务器上能装 ripgrep,用 rg,快很多,而且默认跳过 .git 之类的目录。
第三层,机器现在什么状态
top 或 htop、df -h、du -sh * | sort -h、free -h、nvidia-smi
这一层是排查能力的核心。程序不动了的时候,我的固定顺序是:先看卡,再看进程,再看 CPU 和内存,再看磁盘,最后才怀疑代码。
从外往里查,这个顺序能省掉大量白干的时间。我吃过教训,改了两小时代码,最后发现是磁盘写满了。
第四层,管住长时间任务
ps、kill、tmux
这一层对做实验的人是分水岭。
tmux 我要单独推一下,它是新手学 Linux 投入产出比最高的一个东西。
场景是:你 ssh 上服务器跑训练,然后合上笔记本回宿舍。连接断了,任务也死了。
tmux 在服务器上开一个不依赖你连接的会话,你断线它照跑。三个操作就够用:
tmux new -s train
Ctrl+B 然后按 D 脱离。
tmux attach -t train
学十分钟,能救你几十次。
第五层,传输和权限
scp、rsync、chmod、chown、tar
传大批文件不要用 scp,用 rsync。因为 rsync 能续传,只传有变化的部分。传一次两百 G 的数据集,中间断了,scp 从头来,rsync 接着走。
这个差别在实验室是天大的差别。
第六层,会自己查
命令 --help、man 命令、tldr 命令
这一层其实应该最早学,我放最后是因为它是一个习惯而不是一个命令。下面单独讲。
六、四个提速习惯,比多学十个命令管用
Tab 补全,而且要当成校验工具用
Tab 补全所有人都知道能省字。但它更重要的作用是校验。
你敲一半按 Tab,补不出来,说明这个路径不存在或者你拼错了。这比你敲完回车再看报错快得多。
我现在敲长路径几乎全靠 Tab 一节一节点过去,很少手打完整路径。这不只是快,是不容易错。
Ctrl+R 反向搜历史
按下 Ctrl+R,输入几个字符,它会把你以前敲过的、含这几个字符的命令翻出来。
我的训练启动命令有七八十个字符,我从来不重新敲,我按 Ctrl+R 然后打 train。
配套的还有 !!,代表上一条命令。最经典的用法是命令报权限不足,然后敲:
sudo !!
等于用 sudo 重跑刚才那条。我第一次看到这个设计的时候真的觉得优雅。
行内编辑快捷键
光标在长命令里靠方向键一格一格挪,太慢了。
Ctrl+A 跳到行首。 Ctrl+E 跳到行尾。 Ctrl+U 清空整行。 Ctrl+W 删掉光标前一个词。 Ctrl+L 清屏。
就这五个,一周就能变成肌肉记忆。
alias
把你天天敲的长命令起个短名字,写进 .bashrc。
我自己常用的几个:
alias ll='ls -ltrh' alias gpu='watch -n 1 nvidia-smi'
不过 alias 有个反作用要提醒:不要把危险命令 alias 成安全的样子,也不要 alias 太多,否则你去别人机器上会完全不会干活。我见过有人把 rm alias 成带确认的,结果在没配置的机器上手一滑就出事了。
习惯要长在你身上,不要长在你的配置文件上。
七、怎么查资料,包括怎么用 AI 而不被它坑
先说传统三件套。
命令 --help 最快,看常用选项,八成情况够了。
man 命令 最权威。它就是你这台机器上这个版本的说明书,不像网上的答案可能是三年前另一个版本的。man 里面按 / 搜索,n 跳下一个,q 退出。
tldr 命令 最实用。它不解释原理,直接给五六个最常用的例子。适合「我不想懂,我就想知道怎么写」的场景。需要自己装一下,但值得。
然后说 AI。
我是做这个方向的,我反而想认真提醒一下。
用 AI 学命令行效率确实高,但有几个坑很实在。
第一,它会给你看起来很对但参数错的命令。尤其是不常用的选项,不同版本行为不一样,它有时候会混。所以拿到命令别直接回车,先 --help 扫一眼那个参数是否存在。
第二,绝对不要直接执行 AI 给你的、带 rm、sudo、chmod -R、mv 到系统目录的命令。这几类命令错了是不可逆的。
第三,正确的用法不是让它给答案,是让它解释。你把一串你看不懂的命令粘给它,让它逐段拆开告诉你每一部分在干什么。这样你学到的是可迁移的理解,而不是一次性的答案。
第四,先在安全的地方试。新建一个空目录,造几个假文件,在里面试完再去动真数据。
说白了,AI 是很好的解释器,但你得保留那个「我知道这条命令会做什么」的判断权。这个判断权一旦交出去,出事就是真出事。
八、怎么练:三个真能积累起来的办法
一,强迫自己用命令行做日常事
有图形界面的时候人是很难忍住不用鼠标的。所以要有意识地逼一下自己。
改远程配置文件,别用编辑器插件同步,用 vim 直接改。 看日志,别下载到本地,用 tail -f。 传文件,别用图形工具,用 scp 或 rsync。 统计东西,别导出到 Excel,用 grep 加 wc -l。
前两周会很痛苦,慢得想砸键盘。第三周开始你会发现你比用鼠标快了。
二,维护一个只记坑的笔记
这条我强烈推荐。
不要抄教程,教程网上有。你要记的是你自己踩过的坑。
我的笔记里长这样:
磁盘明明有空间却写不进去,敲 df -i 看 inode,小文件太多会把 inode 占满。这个坑我找了一下午。
scp 传目录忘了加 -r,会提示不是普通文件。
tar 解压到当前目录会炸出一堆文件,先 tar -tf 看一眼里面结构。
这种笔记的价值在于,它是你自己的痛点索引。一年后你翻它,每一条都能立刻想起当时的场景。教程你翻十遍也记不住,自己的坑看一遍就够。
三,给自己造一个可以随便搞坏的地方
这条能极大降低你的心理负担。
在本地起一个容器,或者装个虚拟机,把它当沙盒。
docker run -it --rm ubuntu bash
在里面你可以随便 rm -rf,随便改权限,随便把环境搞烂。搞烂了退出,重新起一个,干干净净。
新手最大的心理障碍是怕搞坏东西,所以不敢试,不敢试就学不会。给自己一个允许搞坏的地方,这个障碍就没了。
顺便,--rm 的意思是容器退出就删掉,不留垃圾。
四,拿真实的小需求练手
练习题式的学习没有痛感。找几件你真的需要做的小事:
把一个目录里三百个文件按规则批量重命名。 从日志里统计每小时的请求量。 找出整个项目里所有超过 100 M 的文件。 把三十个 CSV 合并成一个,但只保留第一个的表头。
这四件事我都干过,每一件都能逼你学会两三个新东西。而且做完你是真的解决了一个问题,那种正反馈跟做练习题完全不一样。
九、几条我希望有人早点告诉我的警告
rm -rf 之前先用 ls 看一遍。
我们组有个师兄,博士第四年,跑了两周的实验结果,一条命令清空。路径里多打了一个空格。他那天没发脾气,就是坐在那很久没动,然后站起来去打了杯水,回来重写脚本。
我当时在旁边一句话不敢说。从那以后我给自己定了死规矩:删之前必须先用 ls 把要删的东西列一遍,确认列出来的确实是我想删的。
多花三秒,省两周。
另外,绝对不要写 rm -rf $DIR/ 这种形式。如果 $DIR 因为任何原因是空的,这条命令就变成了删根目录。这不是理论风险,这是真实发生过的事故类型。
在共享服务器上动手之前先 pwd。
这个命令毫无技术含量,但它是防灾用的。你以为自己在自己的目录,其实在别人的。
批量 kill 进程要极其小心。范围写大了,可能把同门跑了三天的任务一起送走。那已经不是技术问题了。
不要往系统目录随便装东西。用 conda 环境或者虚拟环境,别 sudo pip install。你污染了共享服务器的全局环境,全组都会受影响,而且很难查。
Ctrl+C 和 Ctrl+Z 不一样。前者是终止,后者是挂起到后台,进程还在。很多人以为按了 Ctrl+Z 就停了,结果显存还被占着,回头发现卡上挂着一堆幽灵进程。想恢复用 fg,想真杀掉先 jobs 看编号再 kill。
十、最后说点心态上的东西
命令行的学习曲线不是斜坡,是台阶。
你会有很长一段时间感觉自己在原地踏步,天天敲那五六个命令,什么都没进步。然后某一天你遇到一个问题,突然发现你能一路查下去,从磁盘查到进程,从进程查到日志,最后定位到根因。
那一刻你会知道自己上了一层台阶。
这个过程没法加速,它需要你真的在机器上待够时间,真的被坑够次数。
还有一件事我想说。
命令行的报错,是我遇到过最诚实的老师。
它从不安慰你,也从不含糊。No such file or directory、Permission denied、command not found,每一句都精确地告诉你哪里不对。
刚开始你会觉得它冷冰冰的,甚至有点凶。但用久了你会发现这是一种很好的关系。它不猜你的意图,不替你做决定,你说什么它就做什么。
图形界面是别人替你想好了你要什么,然后做了个按钮。命令行是你自己知道你要什么,然后直接说出来。
这两种关系是不一样的。
我研一那会儿特别怕那个黑窗口,看师兄哗哗敲一串东西,觉得是某种法术。
后来我发现根本不是法术,那就是熟练。他敲得快不是因为记性好,是因为他在那个环境里待得够久,机器出问题的样子他见过太多次,所以他知道该往哪看。
命令是工具,直觉才是能力。
所以如果你现在正卡在那个「什么都不会、连自己在哪都不知道」的阶段,我的建议特别朴素:别急着学一百个命令,先把 pwd、ls -la、which、echo $PATH 这四个用熟。
就这四个。当年师兄给我的就是这四个。
它们不炫技,但它们回答的是最根本的四个问题:我在哪,这里有什么,我用的到底是哪个程序,系统是按什么顺序找它的。
搞清楚这四件事,你就不是在黑屋子里瞎摸了。
剩下的,交给时间和坑。