背景
最近又要在公司的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--login
option.
顺便还有interactive shell的定义:
An interactive shell is one started without non-option arguments and without the
-c
option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the-i
option.
可知有:
- 交互式的 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中也建议使用绝对路径),所以暂且不管。