背景
最近又要在公司的CentOS上配一遍开发环境,这就避不了要编辑一番PATH,那么问题来了,这是要写在/etc/profile、~/.profile、~/.bash_profile还是~/.bashrc或~/.bash_login呢?首先,可以排除影响全局的/etc/profile,这改了听起来就是给后来的自己挖坑(还有一个/etc/bash.bashrc)。接着我们就要厘清后四个的区别了,这就要从login shell和non-login shell的区别说起。
定义
不用Google,有事先找man。
1 | > man bash |
我们在bash的手册中INVOCATION一节就可以找到login shell的定义:
A login shell is one whose first character of argument zero is a
-, or one started with the--loginoption.
顺便还有interactive shell的定义:
An interactive shell is one started without non-option arguments and without the
-coption whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the-ioption.
可知有:
- 交互式的 login shell:本地登录、ssh登录、
bash --login、su - <user>; - 交互式的 non-login shell:
su <user>; - 非交互的 non-login shell:
ssh example.com my-script-which-is-on-the-remote-machine; - 非交互的 login shell:脚本中使用
--login(如#!/bin/bash --login);
上述的情况并没有列全,可以通过如下方法区分login和non-login shell:
1 | > echo $0 |
发生了什么
当一个bash是以交互式的login shell被调用时,它首先会读取/etc/profile文件,然后按照~/.bash_profile,~/.bash_login和~/.profile的顺序依次查找并读取,但这是短路式的,按顺序成功读取了三者之一就不继续往后查找了。最后在退出时会执行~/.bash_logout中的命令。
而交互式的non-login shell则先后读取/etc/bash.bashrc和~/.bashrc。
非交互的non-login shell只展开环境变量BASH_ENV并执行其指向的文件。
总结一下
如果需要统一交互式的login shell和non-login shell环境,我们可以在~/.bashrc中编写配置,然后在~/.bash_profile读取~/.bashrc。非交互式的情况一般与脚本有关,一般是主动载入环境变量(因为环境变量问题,dockerfile中也建议使用绝对路径),所以暂且不管。