随便说说
上篇文章,我推荐了一个对用户良好的Shell——Fish,然后又想到了一个关键问题,Shell的本质到底是什么?所以我就重新回顾了一下Shell的定义,感触良多,特地写多一篇文章讲一讲,过程中我还会讲到 Bash、source和profile
等内容。
Shell是什么?
-
Shell 是一个命令行界面(CLI)程序,充当用户与操作系统内核之间的中介。它允许用户通过输入命令与操作系统交互,执行各种任务,如文件管理、程序执行、系统监控等。简单来说,Shell 是用户和操作系统之间的沟通桥梁。
-
常见的Shell包括:
- Bash (Bourne Again Shell):Linux 系统上最常用的 Shell,几乎所有 Linux 系统默认都使用它。
- Zsh (Z Shell):一种功能强大的 Shell,提供更多的自动补全和脚本功能。
- Fish (Friendly Interactive Shell):注重易用性和互动体验,界面友好,支持现代化的特性。
Shell的四大模式
- 登陆模式:用户登录时启动的 Shell,是最常见的模式。比如使用
ssh
登陆,使用su - <用户名>
切换用户,在图形界面下启动终端,都属于登陆模式。 - 非登陆模式:Shell本身也是个程序,所以我们可以用运行程序的方式去运行它,比如在命令行下直接输入
bash
运行,或者使用bash <脚本>
来让bash执行某个脚本,这些都属于非登陆模式。 - 交互模式:用户可以与Shell进行交互,通常用于执行命令和查看结果。
- 非交互模式:Shell自动执行命令,通常用于脚本和批量任务,不需要用户输入。
总结一下,当我们正常登陆Shell时,我们都处于登陆模式和交互模式。当我们在Shell下以程序的方式运行Shell时,就处于非登陆模式和交互模式。特别的,如果我们使用Shell就执行某个脚本时,就会处于非登陆模式和非交互模式了。
环境变量
- 环境变量本质上是一些存放配置信息的值,这些值在系统和程序运行时都会用到。很多环境变量的名称都是约定好并且是固定的,它们告诉程序一些重要的事情,比如:
- 你在哪里(比如你家目录的位置 HOME)。
- 哪些文件夹可以找到程序(比如 PATH,告诉系统去哪些文件夹找命令)。
- 你使用的是什么编辑器(比如 EDITOR,指定你用的文本编辑器)。
- 环境变量是一组动态值,Shell每次运行的时候,总是会加载系统设置的一些默认环境变量,我们也可以在Shell中对环境变量进行增删改查。
- 值得注意的是,无论你在Shell中对环境变量做什么改动,这些修改都会随着当前Shell的关闭而消失。
- 环境变量具有继承属性,比如我们在当前Shell中运行了一个子Shell,这个子Shell会继承父Shell的所有环境变量,以下实验可以很好地说明这个特性。
- 以登陆模式登陆Shell,比如打开终端,ssh连接等。
- 执行以下命令查询环境变量a,发现a没有定义值。
echo $a
- 给a定义值,并且再次查询,发现a的值已经定义为1了
export a=1 echo $a
- 创建子Shell,并且在子Shell中查询a,发现a值确实被定义
bash echo $a
- 在子Shell中查询b,发现b没有定义值,然后定义b值为2
echo $b export b=2 echo $b
- 退出子Shell,此时我们在父Shell查询a和b,发现a值定义仍在,但b值却随着子Shell的消失而不见了
exit echo $a echo $b
执行脚本
我们执行Shell脚本的方式有两种,一种是直接通过Shell执行,比如 bash <脚本名称>
,还有一种是通过Source执行,比如 source <脚本名称>
,那么它们两者有什么不同吗?
- Shell方式:创建子Shell,以非登陆非交互模式执行脚本,脚本中涉及对环境变量的修改都只会在子Shell中生效。一旦脚本执行结束,子Shell退出,父Shell不会保留任何子Shell中的环境变量。
- Source方式:直接在当前Shell中执行脚本,脚本中涉及对环境变量的修改都会在当前Shell中生效,直到当前Shell退出。
配置文件
- 环境变量虽然会随着Shell的退出而消失,但我们可以通过配置文件来设置默认环境变量,使得每次进入Shell时都会自动加载。
- 大部分Linux系统中都会存在以下几个文件,在这些文件中都可以设置默认环境变量,但效果却不一样
/etc/profile ~/.profile /etc/bashrc ~/.bashrc
- 需要注意,部分系统中可能没有
bashrc
文件,但会存在bash.bashrc
文件,它们本质上是一样的。 - 首先是作用域,
/etc
开头的文件,都是与系统相关,直接作用于所有用户,而~/
开头的文件,则只作用于该文件所属的用户。这也很好理解,本来~
就是表示用户的家目录,其他用户就不应该去读取。 - 在登陆模式下,Shell会去自动加载并执行
/etc/profile
和~/.profile
文件,其中有关对环境变量的命令也会自动执行,以此达到自动加载环境变量的效果。比如我们可以在其中设置PATH,给PATH增加路径:# 以下命令请添加到/etc/profile或~/.profile文件末尾 export PATH=$PATH:/aaa/bbb
- 如果是非登陆模式下,Shell不会读取任何的
profile
文件,而是只读取~/bashrc
文件。并且该文件属于bash独有,也就是说,如果以非登陆模式下执行其他Shell,如Fish,则不会读取~/bashrc
文件。但相对应的,类似于Bash,Fish也有自己独有的配置文件,这方面内容请查阅官方文档。 - 如果你自己有去尝试的话,会发现个很奇怪的现象,明明我把环境变量只定义在
profile
文件中,但是如果尝试以非登陆模式进入Shell时,还是能读取到该环境变量。这个问题其实很简单,因为环境变量具有继承属性,当前Shell的父Shell已经默认加载了profile
文件中的环境变量了,那么子Shell当然也会有。 - 需要注意的是,
/etc/bashrc
文件在任何时候,都不会被读取和执行,因此不要在该文件中进行设置。
评论