echo $0显示当前正在用的 Shell,登录 shell 前面会带 -。
约 1326 字大约 4 分钟
2026-05-14
第一次打开终端的人,常常把"黑窗口""命令行""Shell""bash"当成同一个东西。它们其实是不同的层次:终端负责显示和收键盘,Shell 负责把你敲的文字解释成程序调用。分清这几层,后面遇到"为什么脚本里跑不出交互时的结果"才不会困惑。
分清终端、Shell、命令和脚本这几层,理解交互环境和脚本环境的区别,先把命令行世界的边界画清楚。
echo $0显示当前正在用的 Shell,登录 shell 前面会带 -。
ps -p $$$$ 是当前 Shell 的 PID,能看到它到底是 bash 还是 zsh。
echo $SHELL来自 /etc/passwd 的设置,不一定等于此刻在用的 Shell。
cat /etc/shells列出系统里允许作为登录 Shell 的程序。
这四个词经常混用,但职责完全不同:
| 名称 | 是什么 | 举例 |
|---|---|---|
| 终端(terminal) | 显示文字、接收键盘输入的窗口程序 | GNOME Terminal、iTerm2、Windows Terminal |
| Shell | 读取你输入的文字,解释成命令并执行的程序 | bash、zsh、sh |
| 命令 | 一个具体的可执行程序或 Shell 内建功能 | ls、cd、grep |
| 脚本 | 把一串命令写进文件,交给 Shell 批量执行 | deploy.sh |
可以这样理解:终端是"桌子和纸笔",Shell 是"听你说话并去办事的人",命令是"它能做的一件件具体的事",脚本是"提前写好的一张待办清单"。SSH 登录远程服务器时没有图形终端,但仍然有 Shell——因为真正解释命令的是 Shell,不是那个窗口。
最常见的几种 Shell,语法相近但并不完全兼容:
/bin/sh 通常指向 dash,它不支持 bash 的很多扩展语法。这意味着同一个脚本,bash script.sh 能跑,sh script.sh 可能就报错。所以脚本第一行要写清解释器:
#!/usr/bin/env bash而不是依赖"我本地默认就是 bash"。
Shell 启动时分两个维度,它决定了哪些配置文件被读取:
| 启动方式 | 类型 | 读取的配置 |
|---|---|---|
SSH 登录、su - | 登录 + 交互 | /etc/profile、~/.bash_profile 或 ~/.profile |
| 在桌面终端开新标签 | 非登录 + 交互 | ~/.bashrc |
执行一个 .sh 脚本 | 非登录 + 非交互 | 默认什么都不读 |
这就解释了一个高频困惑:在终端里手敲命令好好的,放进脚本或 cron 里就"command not found"。因为脚本是非交互 Shell,不会加载 ~/.bashrc,你在 .bashrc 里设的 PATH、alias 全都不存在。
echo $0 # 当前 Shell,如 -bash / zsh
ps -p $$ # 看当前 Shell 进程的真实程序名
echo $SHELL # 登录时的默认 Shell(来自 /etc/passwd)
bash --version # 确认版本,老系统的 bash 3.x 缺少新语法注意 $SHELL 是"默认登录 Shell",如果你登录后手动敲了 zsh,$SHELL 仍然显示 bash,而 echo $0 会显示 zsh。排查脚本问题时,以 ps -p $$ 的结果为准。
改默认 Shell 要谨慎
chsh -s /bin/zsh 会修改登录 Shell。改之前先确认目标 Shell 在 /etc/shells 里、且配置文件已经准备好,否则下次登录可能进入一个没有 PATH、没有提示符的环境。先用 zsh 命令临时切换试用,确认没问题再改默认。
| 误区 | 更稳妥的做法 |
|---|---|
| 把终端软件和 Shell 当成一回事 | 终端只管显示,真正执行命令的是 Shell;换终端软件不会改变 Shell 行为 |
| 假设脚本环境和交互环境一样 | 脚本是非交互 Shell,不读 ~/.bashrc;脚本里要用的命令写绝对路径或显式设 PATH |
| 脚本不写 shebang,靠"默认是 bash" | 第一行写 #!/usr/bin/env bash,避免被 sh 执行时语法报错 |
版权归属:Shuo Liu