bash 调用方式与配置文件
在做bash环境配置时,会遇到配置应该写到哪个文件里的问题。以centos7.5为例就有/etc/profile
、/etc/bashrc
、$HOME/.bash_profile
、$HOME/.profile
、$HOME/.bashrc
这么多配置文件。本文从login shell和interactive shell两个角度交叉描述各种情况下配置文件的加载情况。参考man bash
。
定义
登录shell的定义很简单
第零位启动参数的首个字符为-
,或启动参数中包含--login
的shell。交互式shell的定义稍微复杂一点
一个不包含“non-option arguments”并且没有-c
参数的shell,它的输入和错误都连接到终端。或者一个启动参数包含-i
的shell。
这里的“non-option arguments”就是不包含在选项范围内的参数,也就是将要执行的脚本文件。比如bash SOME_SCRIPT_FILE
。
以-c
参数启动的bash,将会启动一个bash,而后调用exec函数族执行参数中指定的程序。
获取bash
从定义可以看到,登录shell和交互式shell是从两个正交的角度描述的,因此可以取得的bash类型可以有四种
login and interactive shell
既是登录shell,又是交互式shell。首先保证是登录shell,以下四种都是登录shell:
- 从ssh登录得到的bash
- 控制台登录得到的bash
- 以
--login
或-l
参数运行的bash su - USER_NAME
得到的bash
然后保证是交互式shell,那么在启动bash时后面不要接脚本名或
-c
参数既可。login and non-interactive shell
登录shell,且非交互式,比如bash --login SCRIPT_NAME
bash --login -c BIN_FILE
- non-login and interactive shell
非登录shell,但是为交互式,比如- 直接运行
bash
su USER_NAME
,注意这里没有参数-
(login参数)ssh HOST COMMADN
,以ssh连接服务器执行命令的情况实际会启动一个non-login and interactive的shell,具体shell类型取决于/etc/passwd文件中记录的用户shell类型,不做特殊设置一般为bash。因此如果$HOME/.bashrc
文件中有向标准输出打印字符的话,可能会引起远程scp执行错误。这里的逻辑比较特殊,实际调用bash的命令为bash -c COMMAND
,从其他的判断方式看应该是一个非登录且非交互式shell,但是bash源码中做了一个额外的判断,如果是由sshd或rshd启动且是一个首层shell,则会加载~/.bashrc
文件。
- 直接运行
- non-login and non-interactive shell
非登录shell,且非交互式。普通的非交互式shell一般就是非登录shell,注意不要增加login参数既可,比如bash SCRIPT_NAME
bash -c BIN_FILE
配置加载
在各个固定位置的配置文件之外,有一个稍显特殊的存在,BASH_ENV
环境变量。当启动一个非交互式bash时,会查找该环境变量内容,并将内容当做一个文件路径,加载该文件。
1 | +-----------+---------------------------------------+---------------------------------------+ |
上表结果的验证方式如下:
- 清空系统和用户配置文件,在每个配置文件中写入各自独立的变量,不要export。
- 配置
BASH_ENV
变量,export
使其成为环境变量,变量内容为一个配置文件路径。 - 启动各种类型的bash,并观察变量值。
1 | -bash-4.2$ export BASH_ENV=/home/huyu/bashenv |
1 | -bash-4.2$ . t.sh |
1 | -bash-4.2$ bash |
1 | -bash-4.2$ bash --login t.sh |
1 | -bash-4.2$ bash t.sh |
配置模板
/etc/skel/
目录下的文件是bash配置的模板文件,在添加新用户时,会被拷贝到新用户的HOME目录作为默认配置。
1 | [huyu@centos1804 ~]$ ll /etc/skel/ -a |
合理配置
前文描述了login shell和interactive shell的区分,与各种情况下bash加载配置文件的区别。这里给出一个合理的配置参考。以centos7.5为例。
/etc/profile
放置系统的环境变量配置$HOME/.bash_profile
放置个人的环境变量配置,并加载$HOME/.bashrc
。由于登录shell不会自动加载$HOME/.bashrc
,为了保证bash配置生效的一致性,这里应当主动加载$HOME/.bashrc
。$HOME/.bashrc
放置个人bash相关配置,并加载/etc/bashrc
。这里不应该放置环境变量相关配置,因为嵌套多次运行bash时该文件会被多次加载,会导致环境变量的配置冗余。/etc/bashrc
放置系统的bash相关配置。centos7.5下这个文件不会被自动加载,因此需要被用户主动加载才能生效。
PS:
$HOME/.profile
这个文件只有在$HOME/.bash_profile
不存在时才会被自动加载,在使用时注意该情况既可,使用场景同$HOME/.bash_profile
/etc/bash.bashrc
Ubuntu下非登录的交互式bash会自动加载该文件。使用方式可以参考centos下的/etc/bashrc
,区别只是自动加载与主动加载。