启动shell

在你登入Linux系统启动一个bash shell时,默认情况下bash会在几个文件中查找命令。这些 文件叫作启动文件或环境文件。bash检查的启动文件取决于你启动bash shell的方式。启动bash shell有3种方式:

  1. 登录时作为默认登录shell
  2. 作为非登录shell的交互式shell
  3. 作为运行脚本的非交互shell

登录shell

当你登录Linux系统时,bash shell会作为登录shell启动。登录shell会从5个不同的启动文件里 读取命令:

  1. /etc/profile
  2. $HOME/.bash_profile
  3. $HOME/.bashrc
  4. $HOME/.bash_login
  5. $HOME/.profile

/etc/profile文件是系统上默认的bash shell的主启动文件。系统上的每个用户登录时都会执行这个启动文件。

/etc/profile文件

/etc/profile文件是bash shell默认的的主启动文件。只要你登录了Linux系统,bash就会执行 /etc/profile启动文件中的命令。

$HOME目录下的启动文件

剩下的启动文件都起着同一个作用:提供一个用户专属的启动文件来定义该用户所用到的环境变量。大多数Linux发行版只用这四个启动文件中的一到两个:

  1. $HOME/.bash_profile
  2. $HOME/.bashrc
  3. $HOME/.bash_login
  4. $HOME/.profile

注意,这四个文件都以点号开头,这说明它们是隐藏文件(不会在通常的ls命令输出列表中 出现)。它们位于用户的HOME目录下,所以每个用户都可以编辑这些文件并添加自己的环境变量,这些环境变量会在每次启动bash shell会话时生效。

shell会按照按照下列顺序,运行第一个被找到的文件,余下的则被忽略:

$HOME/.bash_profile 
$HOME/.bash_login
$HOME/.profile

注意,这个列表中并没有$HOME/.bashrc文件。这是因为该文件通常通过其他文件运行的。

交互式shell进程

如果你的bash shell不是登录系统时启动的(比如是在命令行提示符下敲入bash时启动),那 么你启动的shell叫作交互式shell。交互式shell不会像登录shell一样运行,但它依然提供了命令行 提示符来输入命令。

如果bash是作为交互式shell启动的,它就不会访问/etc/profile文件,只会检查用户HOME目录 中的.bashrc文件。

.bashrc文件有两个作用:

一是查看/etc目录下通用的bashrc文件,

二是为用户提供一个定制自己的命令别名和私有脚本函数的地方。

非交互式shell

最后一种shell是非交互式shell。系统执行shell脚本时用的就是这种shell。不同的地方在于它没有命令行提示符。

为了处理这种情况,bash shell提供了BASH_ENV环境变量。当shell启动一个非交互式shell进 程时,它会检查这个环境变量来查看要执行的启动文件。如果有指定的文件,shell会执行该文件 里的命令,这通常包括shell脚本变量设置。

那如果BASH_ENV变量没有设置,shell脚本到哪里去获得它们的环境变量呢?别忘了有些shell脚本是通过启动一个子shell来执行的。子shell可以继承父shell导出过的变量。

举例来说,如果父shell是登录shell,在/etc/profile、/etc/profile.d/*.sh和$HOME/.bashrc文件中设置并导出了变量,用于执行脚本的子shell就能够继承这些变量。

要记住,由父shell设置但并未导出的变量都是局部变量。子shell无法继承局部变量。

对于那些不启动子shell的脚本,变量已经存在于当前shell中了。所以就算没有设置BASH_ENV,也可以使用当前shell的局部变量和全局变量。

环境变量持久化

对全局环境变量来说(Linux系统中所有用户都需要使用的变量),可能更倾向于将新的或修改过的变量设置放在/etc/profile文件中,但这可不是什么好主意。如果你升级了所用的发行版, 这个文件也会跟着更新,那你所有定制过的变量设置可就都没有了.

最好是在/etc/profile.d目录中创建一个以.sh结尾的文件。把所有新的或修改过的全局环境变量设置放在这个文件中。

在大多数发行版中,存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件。这一点适用于所有类型的shell进程。但如果设置了BASH_ENV变量,那么记住,除非它指向的是 $HOME/.bashrc,否则你应该将非交互式shell的用户变量放在别的地方。