从零开始
目录

02 · 操作系统 · Linux

认识 Shell:bash 与环境变量

本篇你将学到

  • 终端和 shell 有什么区别,bash 和 zsh 是什么关系
  • 怎么看自己用的是哪个 shell,怎么换
  • 环境变量和 PATH:为什么会“未找到命令”
  • ~/.bashrc、~/.profile 配置文件,别名、历史记录、Tab 补全

Shell:终端里的“翻译”

上一篇(02-17)打开的“终端”只是个窗口,负责显示文字、接收键盘输入。真正读懂命令并执行的,是窗口里运行的 shell。好比终端是电话机,shell 是电话那头帮你办事的接线员。

GNU 的 bash 手册这样介绍 shell:它既是命令解释器,也是一门编程语言,可以把命令写成脚本,自动完成重复的工作[1]。它还有很多方便手动操作的功能:命令行编辑、历史记录、别名等[1]。

bash 和 zsh

  • bash 是 GNU 项目的 shell。在 Ubuntu 上,新建用户默认的登录 shell 就是 /bin/bash[2],大多数发行版也是如此。
  • zsh 是 Mac 的默认 shell(见 02-12)。两者大部分写法相同,本篇学的 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-19),再 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 补全和历史。

模拟实操 · bash:PATH、配置文件与别名纯模拟,命令不会真的执行

    可以直接打字,也可以点上面的命令按钮把命令填进去,再按回车(或点“运行”)。↑ 键翻出上一条命令。按 Tab 键(手机上点“Tab ⇥”)自动补全。“新开一个终端窗口”会像真的一样重新开始:临时设置会消失,配置文件和历史记录会保留。输入 help 看看支持哪些命令。

    小结

    • 终端是窗口,shell 是解释命令的程序;Ubuntu 默认 bash,echo $SHELL 查看,chsh -s 更换。
    • PATH 是冒号隔开的文件夹列表,从左到右找命令。
    • 临时:export PATH="$HOME/tools:$PATH";终端里永久:写进 ~/.bashrc;图形程序也要用的变量:写进 ~/.profile,重新登录。
    • alias 起外号,history 看历史,Tab 自动补全。

    参考资料

    1. [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. [2]adduser.conf(5)(DSHELL 默认值) · Ubuntu Manpages
      https://manpages.ubuntu.com/manpages/resolute/en/man5/adduser.conf.5.html
    3. [3]chsh(1) · man7.org(util-linux)
      https://man7.org/linux/man-pages/man1/chsh.1.html
    4. [4]Bash Reference Manual: Environment · GNU
      https://www.gnu.org/software/bash/manual/html_node/Environment.html
    5. [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. [6]Bash Reference Manual: Bash Startup Files · GNU
      https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html
    7. [7]EnvironmentVariables(Ubuntu 社区帮助 Wiki 存档) · Ubuntu(GitHub: ubuntu/wiki-archives)
      https://github.com/ubuntu/wiki-archives/blob/main/UbuntuCommunityHelpWiki/E/EnvironmentVariables.wiki
    8. [8]Bash Reference Manual: Aliases · GNU
      https://www.gnu.org/software/bash/manual/html_node/Aliases.html
    9. [9]Bash Reference Manual: Bash History Facilities · GNU
      https://www.gnu.org/software/bash/manual/html_node/Bash-History-Facilities.html
    10. [10]Bash Reference Manual: Letting Readline Type For You · GNU
      https://www.gnu.org/software/bash/manual/html_node/Commands-For-Completion.html