關於「.bash_profile」和「.bashrc」區別的總結

bash的startup文件

Linux shell是用戶與Linux系統進行交互的媒介,而bash做爲目前Linux系統中最經常使用的shell,它支持的startup文件也並不單一,甚至容易讓人感到費解。本文以CentOS7系統爲例,對bash的startup文件進行一些必要的梳理和總結。shell

根據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文件的做用是相同的。bash

備註:Debian系統會使用~/.profile文件取代~/.bash_profile文件,所以在相關細節上,會與CentOS略有不一樣。less

「profile」與「rc」系列

經過名字的不一樣,咱們能夠直觀地將startup文件分爲「profile」與「rc」兩個系列,其實他們的功能都很相似,可是使用的場景不一樣,這也是你們最容易忽略的地方。ide

所謂的不一樣場景,其實就是shell的運行模式。咱們知道運行中的bash有「交互」和「登錄」兩種屬性,而執行「profile」系列仍是「rc」系列,就與shell的這兩個屬性有關。this

關於bash的運行模式,請參見個人另外一篇博客: 
關於「交互式-非交互式」與「登陸-非登錄」shell的總結idea

原理上講,「登錄shell」啓動時會加載「profile」系列的startup文件,而「交互式非登錄shell」啓動時會加載「rc」系列的startup文件。spa

「profile」系列的執行場景

根據bash手冊上的描述:.net

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.code

「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」的實驗結果以下:

[root@localhost ~]# 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 [root@localhost ~]# 

咱們看到,由於執行了~/.bash_profile文件,因此優先級更低的~/.bash_login~/.profile文件並無被執行。 
咱們能夠刪除~/.bash_profile~/.bash_login文件,這樣系統就會找到並執行~/.profile文件:

[root@localhost ~]# mv /home/chen/.bash_profile /home/chen/.bash_profile.bak [root@localhost ~]# mv /home/chen/.bash_login /home/chen/.bash_login.bak [root@localhost ~]# 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 [root@localhost ~]# 

非交互式登錄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」的實驗結果以下:

[root@localhost ~]# su chen execute ~/.bashrc bash-4.2$ exit exit [root@localhost ~]# 

startup文件的默認調用關係

細心的用戶會發現,startup文件的加載並不像上面所述的那樣簡單。這是由於在CentOS中,startup文件之間還存在着默認的顯式調用關係,它們是: 
1. ~/.bash_profile顯式調用~/.bashrc文件; 
2. ~/.bashrc顯式調用/etc/bashrc文件;

再看startup文件

分別打開/etc/profile/etc/bashrc兩個文件,咱們能夠看到:

[root@localhost ~]# 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. [root@localhost ~]# 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文件時,都會擇機調用它們。這樣作最大的好處是便於維護,並且相對更加安全。

這些文件的編寫方法,能夠參考目錄下已有的文件:

[root@localhost ~]# 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文件。

相關文章
相關標籤/搜索