關於“.bash_profile”和“.bashrc”區別的總結
版權宣告:本文為博主原創文章,轉載請註明出處,謝謝合作! https://blog.csdn.net/sch0120/article/details/70256318
bash的startup檔案
Linux shell是使用者與Linux系統進行互動的媒介,而bash作為目前Linux系統中最常用的shell,它支援的startup檔案也並不單一,甚至容易讓人感到費解。本文以CentOS7系統為例,對bash的startup檔案進行一些必要的梳理和總結。
根據bash手冊上的描述:
- /etc/profile The systemwide initialization file, executed for login shells
- /etc/bash.bash_logout The systemwide login shell cleanup file, executed when a login shell exits
- ~/.bash_profile The personal initialization file, executed for login shells
- ~/.bashrc The individual per-interactive-shell startup file
- ~/.bash_logout The individual login shell cleanup file, executed when a login shell exits
此外,bash還支援~/.bash_login
和~/.profile
檔案,作為對其他shell的相容,它們與~/.bash_profile
檔案的作用是相同的。
備註:Debian系統會使用~/.profile
檔案取代~/.bash_profile
檔案,因此在相關細節上,會與CentOS略有不同。
“profile”與“rc”系列
通過名字的不同,我們可以直觀地將startup檔案分為“profile”與“rc”兩個系列,其實他們的功能都很類似,但是使用的場景不同,這也是大家最容易忽略的地方。
所謂的不同場景,其實就是shell的執行模式。我們知道執行中的bash有“互動”和“登陸”兩種屬性,而執行“profile”系列還是“rc”系列,就與shell的這兩個屬性有關。
原理上講,“登陸shell”啟動時會載入“profile”系列的startup檔案,而“互動式非登陸shell”啟動時會載入“rc”系列的startup檔案。
“profile”系列的執行場景
根據bash手冊上的描述:
When bash is invoked as an interactive login shell, or as a non-interactive shell with the
--login
option, it first reads and executes commands from the file/etc/profile
, if that file exists. After reading that file, it looks for~/.bash_profile
,~/.bash_login
, and~/.profile
, in that order, and reads and executes commands from the first one that exists and is readable. The--noprofile
option may be used when the shell is started to inhibit this behavior. When a login shell exits, bash reads and executes commands from the files~/.bash_logout
and/etc/bash.bash_logout
, if the files exists.
“profile”系列的代表檔案為~/.bash_profile
,它用於“登入shell”的環境載入,這個“登入shell”既可以是“互動式”的,也可以是“非互動式”的。
通過--noprofile
選項可以阻止系統載入“profile”系列的startup檔案。
互動式登陸shell
對於互動式的登陸shell而言,CentOS規定了startup檔案的載入順序如下:
登陸過程:
1. 讀取並執行/etc/profile
檔案;
2. 讀取並執行~/.bash_profile
檔案;
- 若檔案不存在,則讀取並執行~/.bash_login
檔案;
- 若檔案不存在,則讀取並執行~/.profile
檔案;
登出過程:
1. 讀取並執行~/.bash_logout
檔案;
2. 讀取並執行/etc/bash.bash_logout
檔案;
為了完成實驗,我新建了一些系統預設沒有提供的startup檔案,例如/etc/bash.bash_logout
。然後在每個檔案中列印了檔名,並將它們之間的顯式呼叫語句註釋掉,例如~/.bash_profile
對~/.bashrc
的顯式呼叫。
“互動式登陸shell”的實驗結果如下:
[[email protected] ~]# su - chen
Last login: Tue Apr 18 17:15:08 CST 2017 from 192.168.161.1 on pts/2
execute /etc/profile
execute ~/.bash_profile
-bash-4.2$ exit
logout
execute ~/.bash_logout
execute /etc/bash.bash_logout
[[email protected] ~]#
- 因為執行了
~/.bash_profile
檔案,所以優先順序更低的~/.bash_login
和~/.profile
檔案並沒有被執行。 我們可以刪除~/.bash_profile
和~/.bash_login
檔案,這樣系統就會找到並執行~/.profile
檔案:
[[email protected] ~]# mv /home/chen/.bash_profile /home/chen/.bash_profile.bak
[[email protected] ~]# mv /home/chen/.bash_login /home/chen/.bash_login.bak
[[email protected] ~]# su - chen
Last login: Tue Apr 18 17:27:21 CST 2017 on pts/1
execute /etc/profile
execute ~/.profile
-bash-4.2$ exit
logout
execute ~/.bash_logout
execute /etc/bash.bash_logout
[[email protected] ~]#
非互動式登陸shell
對於非互動式的登陸shell而言,CentOS規定了startup檔案的載入順序如下:
登陸過程:
1. 讀取並執行/etc/profile
檔案;
2. 讀取並執行~/.bash_profile
檔案;
- 若檔案不存在,則讀取並執行~/.bash_login
檔案;
- 若檔案不存在,則讀取並執行~/.profile
檔案;
我們注意到,與“互動式登陸shell”相比,“非互動式登陸shell”並沒有登出的過程,實驗也證實了這一點:
-bash-4.2$ bash --login -c "uname -r"
execute /etc/profile
execute ~/.bash_profile
3.10.0-514.el7.x86_64
-bash-4.2$ # 此時非互動式shell已退出
“rc”系列的執行場景
根據bash手冊上的描述:
When an interactive shell that is not a login shell is started, bash reads and executes commands from
~/.bashrc
, if that file exists. This may be inhibited by using the--norc
option. The--rcfile
file option will force bash to read and execute commands from file instead of~/.bashrc
.
“rc”系列的代表檔案為~/.bashrc
,它用於“互動式非登入shell”的環境載入。
通過--norc
選項可以阻止系統載入“rc”系列的startup檔案;通過--rcfile
選項可以使用指定的檔案替代系統預設的~/.bashrc
檔案。
互動式非登陸shell
對於互動式的非登陸shell而言,CentOS規定了startup檔案的載入順序如下:
1. 讀取並執行~/.bashrc
或--rcfile
選項指定的檔案
這裡需要說明,其實“rc”系列startup檔案還包括/etc/bashrc
。但是系統並不直接呼叫這個檔案,而是通過~/.bashrc
檔案顯式地呼叫它。
為了完成實驗,我在每個startup檔案中列印了檔名,並將它們之間的顯式呼叫語句註釋掉,例如~/.bashrc
對/etc/bashrc
的顯式呼叫。
“互動式非登陸shell”的實驗結果如下:
[[email protected] ~]# su chen
execute ~/.bashrc
bash-4.2$ exit
exit
[[email protected] ~]#
startup檔案的預設呼叫關係
細心的使用者會發現,startup檔案的載入並不像上面所述的那樣簡單。這是因為在CentOS中,startup檔案之間還存在著預設的顯式呼叫關係,它們是:
1. ~/.bash_profile
顯式呼叫~/.bashrc
檔案;
2. ~/.bashrc
顯式呼叫/etc/bashrc
檔案;
再看startup檔案
分別開啟/etc/profile
和/etc/bashrc
兩個檔案,我們可以看到:
[[email protected] ~]# head /etc/profile
# /etc/profile
# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc
# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.
[[email protected] ~]# head /etc/bashrc
# /etc/bashrc
# System wide functions and aliases
# Environment stuff goes in /etc/profile
# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.
由此可見,“profile”系列檔案的主要目的在於為“登入shell”設定環境變數和啟動程式;而“rc”系列檔案的主要目的在於設定功能和別名。
順便提一句,Linux中“rc”是英文“run command”的縮寫,表示檔案中存放需要執行的命令。其實這也非常符合邏輯,設定功能就要執行shopt
命令,而設定別名要執行alias
命令。與“rc”系列互補,“profile”系列用來設定環境變數,它不會去呼叫這兩個命令,但卻經常需要使用export
語句。不信你可以看一看這兩個檔案。
另外值得一提的是,這兩個檔案同時提到了一個位置:/etc/profile.d
目錄。這個目錄用於存放個性化配置指令碼,你可以把自己需要的全域性配置放入以.sh
結尾的檔案中,系統在執行/etc/profile
和/etc/bashrc
檔案時,都會擇機呼叫它們。這樣做最大的好處是便於維護,而且相對更加安全。
這些檔案的編寫方法,可以參考目錄下已有的檔案:
[[email protected] ~]# ls /etc/profile.d/*.sh
/etc/profile.d/256term.sh /etc/profile.d/colorls.sh /etc/profile.d/less.sh
/etc/profile.d/colorgrep.sh /etc/profile.d/lang.sh /etc/profile.d/which2.sh
總結
對於“登入shell”而言,“互動式”執行“登陸”和“登出”相關的“profile”系列startup檔案,“非互動式”只執行“登陸”相關的“profile”系列startup檔案;對於“非登陸shell”而言,“互動式”執行“rc”系列的startup檔案,而“非互動式”執行的配置檔案由環境變數BASH_ENV
指定。
Linux中startup檔案區分全域性和個人:全域性startup檔案放在/etc
目錄下,用於設定所有使用者共同的配置,除非你清楚地知道你在做的事情,否則不要輕易改動它們;個人startup檔案放在~
目錄下,用於設定某個使用者的個性化配置。
~/.bash_profile
會顯式呼叫~/.bashrc
檔案,而~/.bashrc
又會顯式呼叫/etc/bashrc
檔案,這是為了讓所有互動式介面看起來一樣。無論你是從遠端登入(登陸shell),還是從圖形介面開啟終端(非登陸shell),你都擁有相同的提示符,因為環境變數PS1
在/etc/bashrc
檔案中被統一設定過。
下面我來對startup檔案進行一個完整的總結:
startup檔案 | 互動登陸 | 非互動登陸 | 互動非登陸 | 非互動非登陸 |
---|---|---|---|---|
/etc/profile | 直接執行1 | 直接執行1 | - | - |
~/.bash_profile | 直接執行2 | 直接執行2 | - | - |
~/.bash_login | 條件執行2 | 條件執行2 | - | - |
~/.profile | 條件執行2 | 條件執行2 | - | - |
~/.bash_logout | 直接執行3 | 不執行 | - | - |
/etc/bash.bash_logout | 直接執行4 | 不執行 | - | - |
~/.bashrc | 引用執行2.1 | 引用執行2.1 | 直接執行1 | - |
/etc/bashrc | 引用執行2.2 | 引用執行2.2 | 引用執行1.1 | - |
備註:
1. “直接執行”表示此檔案被系統直接呼叫,它的執行是無條件的;
2. “條件執行”表示此檔案被系統呼叫是有先決條件的(沒有優先順序更高的檔案可用);
3. “引用執行”表示此檔案不是被系統直接呼叫的,而是被其他檔案顯式呼叫的;
4. 後面的數字表示檔案被呼叫的順序,數字越大呼叫越靠後;
5. “非互動非登陸”shell的配置檔案可以由BASH_ENV
環境變數指定;
最後我想說的是,知道startup檔案何時被執行並不是關鍵,關鍵是要理解自己的情況應該去修改哪個startup檔案。
如果你想對bash的功能進行設定或者是定義一些別名,推薦你修改~/.bashrc
檔案,這樣無論你以何種方式開啟shell,你的配置都會生效。而如果你要更改一些環境變數,推薦你修改~/.bash_profile
檔案,因為考慮到shell的繼承特性,這些更改確實只應該被執行一次(而不是多次)。針對所有使用者進行全域性設定,推薦你在/etc/profile.d
目錄下新增以.sh
結尾的檔案,而不是去修改全域性startup檔案。