1. 程式人生 > >關於“.bash_profile”和“.bashrc”區別的總結

關於“.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檔案。