02 · 操作系统 · Linux
认识 Shell:bash 与环境变量
本篇你将学到
- 终端和 shell 有什么区别,bash 和 zsh 是什么关系
- 怎么看自己用的是哪个 shell,怎么换
- 环境变量和 PATH:为什么会“未找到命令”
~/.bashrc、~/.profile配置文件,别名、历史记录、Tab 补全
Shell:终端里的“翻译”
前面(02-21)打开的“终端”只是个窗口,负责显示文字、接收键盘输入。真正读懂命令并执行的,是窗口里运行的 shell。好比终端是电话机,shell 是电话那头帮你办事的接线员。
GNU 的 bash 手册这样介绍 shell:它既是命令解释器,也是一门编程语言,可以把命令写成脚本,自动完成重复的工作[1]。它还有很多方便手动操作的功能:命令行编辑、历史记录、别名等[1]。
bash 和 zsh
- bash 是 GNU 项目的 shell。在 Ubuntu 上,新建用户默认的登录 shell 就是
/bin/bash[2],大多数发行版也是如此。 - zsh 是 Mac 的默认 shell(见 02-15)。两者大部分写法相同,本篇学的
export、alias在 zsh 里也能用。
看看你用的是哪个:
echo $SHELL
显示 /bin/bash 就是 bash。$SHELL 是一个环境变量,下面会讲。
想换 shell(一般不需要):用 chsh -s shell的路径。普通用户只能换成 /etc/shells 文件里列出的 shell[3],可以先 cat /etc/shells 看看。Ubuntu 默认没装 zsh,想用要先 sudo apt install zsh(装软件见 02-24),再 chsh -s /bin/zsh,重新登录后生效。
环境变量与 PATH
环境变量像贴在电脑上的便利贴,每张写着“名字=内容”。程序启动时会收到一整套这样的“名字=值”列表,从 shell 里启动的命令会继承它[4]。
echo $HOME # 你的家目录,比如 /home/xiaoming
echo $SHELL # 你的 shell
echo $PATH # 去哪些文件夹找命令
env # 列出全部环境变量
名字前加 $,shell 就把它换成内容。Linux 上环境变量名分大小写,$PATH 和 $Path 是两个变量[5]。
PATH 是一串用冒号 : 隔开的文件夹[5],比如:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
你输入 ls,shell 就从左到右挨个文件夹去找叫 ls 的程序,用找到的第一个。像查通讯录,通讯录里没有就打不出去。程序在电脑上,但所在文件夹不在 PATH 里,就会看到:
hello:未找到命令
办法有两个:写完整路径(~/tools/hello),或者把 ~/tools 这个文件夹加进 PATH。
临时设置:export
export PATH="$HOME/tools:$PATH"
新的 PATH = ~/tools + 冒号 + 原来的 PATH。export 把变量放进“环境”,之后从这个 shell 启动的命令都能看到[4]。
这样改只管当前这个窗口,关掉就没了。
别写成
export PATH="$HOME/tools":漏了:$PATH,原来的文件夹全没了,连ls都找不到。写错了就关掉窗口重新开一个,自动恢复。
永久设置:~/.bashrc 和 ~/.profile
bash 启动时会读配置文件,读哪个要看它是怎么启动的[6]:
| 启动方式 | 读哪些文件 |
|---|---|
| 登录(比如在文字界面登录、SSH 远程登录) | 先读 /etc/profile,再按顺序找 ~/.bash_profile、~/.bash_login、~/.profile,只读第一个存在的[6] |
| 不是登录、但能交互(比如在桌面上打开一个终端窗口) | ~/.bashrc[6] |
所以常见的做法是:
- 只在终端里用的设置(PATH、别名)写进
~/.bashrc,每开一个终端窗口都会生效; - 想让图形界面里启动的程序也能看到的环境变量,写进
~/.profile。桌面登录时会执行它,改完要注销再登录才生效;写在~/.bashrc里的变量,默认看不到从桌面图标启动的程序[7]。
往 ~/.bashrc 末尾追加一行:
echo 'export PATH="$HOME/tools:$PATH"' >> ~/.bashrc
>> 是追加到末尾。**只有一个 > 会把整个文件覆盖掉!**也可以用 nano ~/.bashrc 打开编辑(Ctrl + O 保存,Ctrl + X 退出)。写好后新开窗口自动生效;想让当前窗口也生效:
source ~/.bashrc
别名:给长命令起外号
alias ll='ls -l'
以后输入 ll,bash 就把它换成 ls -l 再执行[8]。alias 列出所有别名,unalias ll 删掉[8]。别名只在手动敲命令时生效,在脚本里默认不展开[8]。想一直有效,写进 ~/.bashrc。
历史记录和 Tab 补全
- ↑ 方向键翻之前的命令;输入
history列出历史。bash 默认记住最近 500 条,关闭时存进~/.bash_history,下次打开还在[9]。 - Tab 键自动补全:输入开头按 Tab,bash 会补全命令名;以
$开头就补全变量名,以~开头就补全用户名,都不是就补全文件名[10]。比如cd Doc按 Tab,变成cd Documents/。有多个可能时,再按一次 Tab 会列出候选。
动手模拟
在模拟的 bash 里体验:“未找到命令” → 临时加 PATH → 新开窗口又没了 → 写进 ~/.bashrc 永久生效。最后练练别名、Tab 补全和历史。
可以直接打字,也可以点上面的命令按钮把命令填进去,再按回车(或点“运行”)。↑ 键翻出上一条命令。按 Tab 键(手机上点“Tab ⇥”)自动补全。“新开一个终端窗口”会像真的一样重新开始:临时设置会消失,配置文件和历史记录会保留。输入 help 看看支持哪些命令。
小结
- 终端是窗口,shell 是解释命令的程序;Ubuntu 默认 bash,
echo $SHELL查看,chsh -s更换。 - PATH 是冒号隔开的文件夹列表,从左到右找命令。
- 临时:
export PATH="$HOME/tools:$PATH";终端里永久:写进~/.bashrc;图形程序也要用的变量:写进~/.profile,重新登录。 alias起外号,history看历史,Tab 自动补全。
参考资料
- [1]Bash Reference Manual: What is a shell? · GNU
https://www.gnu.org/software/bash/manual/html_node/What-is-a-shell_003f.html - [2]adduser.conf(5)(DSHELL 默认值) · Ubuntu Manpages
https://manpages.ubuntu.com/manpages/resolute/en/man5/adduser.conf.5.html - [3]chsh(1) · man7.org(util-linux)
https://man7.org/linux/man-pages/man1/chsh.1.html - [4]Bash Reference Manual: Environment · GNU
https://www.gnu.org/software/bash/manual/html_node/Environment.html - [5]about_Environment_Variables · Microsoft Learn(PowerShell,含 macOS/Linux 说明)
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables - [6]Bash Reference Manual: Bash Startup Files · GNU
https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html - [7]EnvironmentVariables(Ubuntu 社区帮助 Wiki 存档) · Ubuntu(GitHub: ubuntu/wiki-archives)
https://github.com/ubuntu/wiki-archives/blob/main/UbuntuCommunityHelpWiki/E/EnvironmentVariables.wiki - [8]Bash Reference Manual: Aliases · GNU
https://www.gnu.org/software/bash/manual/html_node/Aliases.html - [9]Bash Reference Manual: Bash History Facilities · GNU
https://www.gnu.org/software/bash/manual/html_node/Bash-History-Facilities.html - [10]Bash Reference Manual: Letting Readline Type For You · GNU
https://www.gnu.org/software/bash/manual/html_node/Commands-For-Completion.html