终端看起来不友好,是因为屏幕上没有东西可点。作为交换,它给了你更好的东西:每个操作都变成一句话,而句子可以重复、组合和自动执行。这一页讲的就是这套语法,还会解释最容易让新手合上电脑的三个报错。
🎙️ 发布并录制于: · 更新于 ·
每条命令都是一个小句子:先是表示程序的动词,再是修改行为的选项,选项通常以短横线开头,最后是要处理的对象。语法就这些。网上那些吓人的单行命令,不过是把这个结构重复几次再接起来。
ls -l /tmp
│ │ └── 对象:哪个目录
│ └────── 选项:“长格式”,显示更多细节
└────────── 动词:列出文件
# 两根救命绳,随时可用:
ls --help # 查看任意命令的简要说明
man ls # 查看完整手册,按 q 退出这里有四个动词:mkdir、cp、mv 和 rm。其中 mv 也负责重命名,因为改名就是把文件移到一个新名字。还有一句必须直说:rm 不经过回收站。没有撤销,没有恢复,也没有“最近删除”。它是系统里最诚实的命令。
mkdir notes # 创建目录
cp report.txt backup.txt # 复制
mv report.txt final.txt # 重命名,本质仍是移动
mv final.txt notes/ # 真正移动文件
rm old.txt # 永久删除文件
rm -r old_project/ # 删除目录及其中所有内容rm -rf / 以及它的近亲,足以毁掉职业生涯。比如 rm -rf ~ /tmp 中多出的空格会删掉你的主目录。两种防护真正有用:不要条件反射地加 -f,它会压掉本该阅读的警告;使用通配符删除之前,先用相同模式执行 ls,确认究竟会删什么。先运行 ls *.log,看清楚,再运行 rm *.log。如果只是看一眼,通常不必打开编辑器。cat 会输出整个文件,less 可以翻页,head 和 tail 分别查看开头与结尾。最像超能力的是 tail -f:它会实时跟踪日志,让你看着错误在用户触发时一条条出现。
cat config.yml # 输出整个文件
less huge.log # 舒服地翻页,按 q 退出,按 / 搜索
head -20 data.csv # 看前 20 行,检查 CSV 的列
tail -50 app.log # 看最后 50 行,崩溃通常在这里
tail -f app.log # 实时跟踪,按 Ctrl+C 停止grep 只做一件事:输出符合某个模式的行。但这已经足够回答“错误在哪儿”“这个设置在哪儿”“这段代码里哪里用到了这个函数”。三个选项承担了百分之九十五的工作:-i 忽略大小写,-r 递归搜索目录,-n 显示行号。
grep "ERROR" app.log # 包含 ERROR 的行
grep -i "timeout" app.log # 忽略大小写
grep -rn "api_key" src/ # 搜索整个目录并显示行号
grep -c "ERROR" app.log # 只统计匹配数
grep -v "DEBUG" app.log # 反选:不含该模式的行竖线这个管道符,会把前一条命令的输出交给后一条命令作为输入。终端的哲学全在这里:每个小工具只做好一件事,再像水管一样接起来。你可以临时组合出答案,不必等别人专门为这个问题写程序。
# “这份日志中最常见的 5 种错误是什么?”
grep "ERROR" app.log | sort | uniq -c | sort -rn | head -5
# 找出错误 合并相同行并计数,
# 按数量降序排列,取前 5 个
# > 把输出保存到文件并覆盖原内容;>> 追加到末尾
grep "ERROR" app.log > errors.txt
echo "new line" >> notes.txt> 会在命令执行之前覆盖目标文件。因此 grep "x" data.txt > data.txt 这种把文件过滤回自身的写法,会立刻清空文件。Shell 先截断 data.txt,grep 随后只能读到空文件。请先写入新文件,再用 mv 换回原名。输入 python 时,Shell 会按顺序搜索一串目录,这串目录就是 Path 环境变量,然后运行第一个匹配项。机制只有这么简单。它也解释了新手最困惑的报错:工具明明装好了,但安装程序把它放进了不在搜索列表里的目录,于是 Shell 如实告诉你,它找不到命令。
$ mytool
bash: mytool: command not found
echo $PATH # 查看用冒号分隔的目录列表
which python # 这个命令最终来自哪个目录?
# 修复:把工具目录加入列表,写进 ~/.bashrc 或 ~/.zshrc
export PATH="$HOME/.local/bin:$PATH"
# 然后重启终端,或运行:source ~/.bashrc~/.bashrc,结果毫无变化,因为这个文件只在终端启动时读取。打开一个新终端,或者在当前终端运行 source ~/.bashrc。“编辑文件,忘记重新加载,以为修复无效,再试一个更糟的办法”几乎是入门仪式;你可以直接跳过。每个文件都有所有者,还有一组开关,分别控制谁能读取、写入和执行。Permission denied 表示你对应的开关没有打开,不代表系统坏了。两条实在的规则:只有任务确实涉及整个系统时才用 sudo;看到 chmod 777 时,把它当成一个碰巧能让报错闭嘴的错误答案。
$ ./deploy.sh
bash: ./deploy.sh: Permission denied
ls -l deploy.sh # -rw-r--r-- ← 没有 x,不能执行
chmod +x deploy.sh # 打开执行权限
./deploy.sh # 运行成功 ✓
sudo apt install nginx # sudo:以管理员身份执行sudo chmod -R 777 .,意思是让所有人都能写入所有内容。它确实“有效”,就像拆掉家门也能“解决”钥匙丢失。如果某个工具在你自己的主目录里总要 sudo,说明它装错了。修复所有权,也就是用 chown,不要把所有权限开关都打开。程序会卡住,端口也会一直被占着。处理时逐级加码:先按 Control 加 C,礼貌地停止前台程序;再用 kill 请后台进程退出;最后才用 kill -9,不再给它收尾的机会。日常经典报错“端口已被占用”,两行就能解决。
Ctrl+C # 停止当前命令,大多数时候都有效
Ctrl+D # “输入完毕”,或退出 Shell
Error: listen EADDRINUSE: address already in use :3000
lsof -i :3000 # 谁占着 3000 端口?结果会显示 PID
kill 12345 # 礼貌请求退出,数字是上一步的 PID
kill -9 12345 # 最后手段:强制终止,不会执行清理按你脑子里冒出的那句话来查。
# “我在哪儿 / 这里有什么 / 去那里”
pwd · ls -la · cd folder · cd .. · cd -
# “这个通配符会删掉什么?”先看,再运行 rm
ls *.log # 确认后才运行: rm *.log
# “这个文件里有什么?”
less file # q 退出,/ 搜索
# “实时查看日志”
tail -f app.log
# “项目里哪里出现了 X?”
grep -rn "X" .
# “最常见的 5 种错误”
grep "ERROR" log | sort | uniq -c | sort -rn | head -5
# “command not found,但我装过了”
echo $PATH · which cmd · add folder to PATH, source ~/.bashrc
# “脚本提示 permission denied”
chmod +x script.sh
# “port already in use”
lsof -i :3000 → kill <PID>这些已经是一套能工作的词汇。更深一层的变化是:终端会把“我做的事”变成“我能保存的句子”。保存下来的句子成为脚本,脚本再成为自动化。这才是每个开发者最后都会来到终端的原因。Git 和 Python 也住在这里,接下来正适合阅读 Git 和 Python。