首先咱們來看系統中的這些文件, 通常的系統可能會有linux
/etc/profile /etc/bashrc ~/.bashrc ~/.profile
而若是系統是 ubuntu 或者 debian 的話, 就不會有 /etc/bashrc 而會有 /etc/bash.bashrc 文件.
以上這些就是經常使用 profile 和 bashrc 文件了. 要理解這些文件以前還須要瞭解 Shell, Shell 的 login(登入) 和 interactive(交互式) 模式.shell
Shell 的分類ubuntu
系統的 shell 有不少種, 好比 bash, sh, zsh 之類的, 若是要查看某一個用戶使用的是什麼 shell 能夠經過 finger [USERNAME] 命令來查看. 咱們這裏只說 shell 是 bash 的狀況, 由於若是是 sh 或者其餘 shell 顯然不會運行 bashrc 的.bash
login shell 和 no-login shell服務器
「login shell」 表明用戶登入, 好比使用 「su -「 命令, 或者用 ssh 鏈接到某一個服務器上, 都會使用該用戶默認 shell 啓動 login shell 模式.
該模式下的 shell 會去自動執行 /etc/profile 和 ~/.profile 文件, 但不會執行任何的 bashrc 文件, 因此通常再 /etc/profile 或者 ~/.profile 裏咱們會手動去 source bashrc 文件.
而 no-login shell 的狀況是咱們在終端下直接輸入 bash 或者 bash -c 「CMD」 來啓動的 shell.
該模式下是不會自動去運行任何的 profile 文件.ssh
interactive shell 和 non-interactive shellserver
interactive shell 是交互式shell, 顧名思義就是用來和用戶交互的, 提供了命令提示符能夠輸入命令.
該模式下會存在一個叫 PS1 的環境變量, 若是還不是 login shell 的則會去 source /etc/bash.bashrc 和 ~/.bashrc 文件
non-interactive shell 則通常是經過 bash -c 「CMD」 來執行的bash.教程
該模式下不會執行任何的 rc 文件, 不過還存在一種特殊狀況這個我以後詳細講述zsh
在可能存在的模式組合中 RC 文件的執行變量
SSH login, sudo su - [USER] 或者 mac 下開啓終端
ssh 登入和 su - 是典型的 interactive login shell, 因此會有 PS1 變量, 而且會執行
/etc/profile ~/.profile
在命令提示符狀態下輸入 bash 或者 ubuntu 默認設置下打開終端
這樣開啓的是 interactive no-login shell, 因此會有 PS1 變量, 只會執行
/etc/bash.bashrc ~/.bashrc
經過 bash -c 「CMD」 或者 bash BASHFILE 命令執行的 shell
這些命令什麼都不會執行, 也就是設置 PS1 變量, 不執行任何 RC 文件
最特殊! 經過 「ssh server CMD」 執行的命令 或 經過程序執行遠程的命令
這是最特殊的一種模式, 理論上應該既是 非交互 也是 非登入的, 可是實際上他不會設置 PS1, 可是還會執行
/etc/bash.bashrc bashrc
這裏還有一點值得注意的是 /etc/bashrc 任何狀況下都不會執行.
bashrc 和 profile 的區別
看了以前那麼多種狀態組合, 最關鍵的問題是, 究竟 bashrc 和 profile 有什麼區別呢?
profile
其實看名字就能瞭解大概了, profile 是某個用戶惟一的用來設置環境變量的地方, 由於用戶能夠有多個 shell 好比 bash, sh, zsh 之類的, 但像環境變量這種其實只須要在統一的一個地方初始化就能夠了, 而這就是 profile.
bashrc
bashrc 也是看名字就知道, 是專門用來給 bash 作初始化的好比用來初始化 bash 的設置, bash 的代碼補全, bash 的別名, bash 的顏色. 以此類推也就還會有 shrc, zshrc 這樣的文件存在了, 只是 bash 太經常使用了而已.
指望的執行順序
=> 表明 在文件內部 source, 換行的 => 表明自身執行結束之後在 source, 同一行表示先 source 在執行自身
普通 login shell
/etc/profile => /etc/bash.bashrc ~/.profile => ~/.bashrc => /etc/bashrc
終端種直接運行 bash
/etc/bash.bashrc ~/.bashrc => /etc/bashrc
bash -c 「CMD」 什麼都不執行
ssh server 「CMD」 /etc/bash.bashrc => /etc/profile ~/.bashrc => | /etc/bashrc => /etc/profile | ~/.profile
這裏會有點小混亂, 由於既有 /etc/bash.bashrc 又有 /etc/bashrc, 實際上是這樣的 ubuntu 和 debian 有 /etc/bash.bashrc 文件可是沒有 /etc/bashrc, 其餘的系統基本都是隻有 /etc/bashrc 沒有 /etc/bash.bashrc.
最終修改
爲了達到上述咱們須要的執行流程, 那必須對系統的 rc 文件作修改. 咱們拿 Ubuntu 舉例
首先 咱們編輯 /etc/profile 在文件頭部加入
export system_profile_loaded=1
這樣其餘文件就能夠根據 $system_profile_loaded 來判斷是否已經載入過 profile, 接着咱們能夠看到
unset i fi if [ "$PS1" ]; then if [ "$BASH" ]; then PS1='\u@\h:\w\$ ' if [ -f /etc/bash.bashrc ]; then . /etc/bash.bashrc fi else if [ "`id -u`" -eq 0 ]; then PS1='# ' else PS1='$ ' fi fi fi umask 022
按照咱們剛纔的方案, 應該是無論任何狀況都應該在文件末尾去載入 bashrc, 因此咱們修改爲
unset i fi umask 022 if [ "$BASH" ]; then if [ "$PS1" ]; then PS1='\u@\h:\w\$ ' fi if [ -f /etc/bash.bashrc ]; then . /etc/bash.bashrc fi else if [ "`id -u`" -eq 0 ]; then PS1='# ' else PS1='$ ' fi fi
固然也能夠有其餘該法,只要符合在文件末尾載入 bashrc 就能夠了.
接着咱們修改 /etc/bash.bashrc, 咱們須要在文件頭加入
[ -n "${system_bashrc_running}" ] && return system_bashrc_running=1 [ -z "${system_profile_loaded}" ] && source /etc/profile unset system_bashrc_running system_bashrc_runned=1
其中 system_bashrc_running 這樣的變量都是爲了防止2次反覆調用而加入的.
這樣系統級別的 rc 文件基本修改好了, 最好還能夠再修改一下本地的rc文件, 因此咱們編輯 「~/.profile」, 發現起內容是
# ~/.profile: executed by Bourne-compatible login shells. if [ -n "$BASH" ]; then if [ -f ~/.bashrc ]; then . ~/.bashrc fi fi mesg n
而按照上述的修改規則只須要替換成
export local_profile_loaded=1 if [ -n "$BASH" ]; then if [ -f ~/.bashrc ]; then . ~/.bashrc fi fi
這樣就始終再載入完 profile 之後去載入 bashrc 了, 接着咱們像編輯 /etc/bash.bashrc 同樣的去修改 ~/.bashrc, 文件頭上加入
[ -n "${local_bashrc_running}" ] && return local_bashrc_running=1 [ -r /etc/bashrc -a -z "${system_bashrc_runned}" ] && source /etc/bashrc [ -r ~/.profile -a -z "${local_profile_loaded}" ] && source ~/.profile unset local_bashrc_running
用來防止反覆加載 profile, 而且這裏須要特殊註明的是
[ -r /etc/bashrc -a -z "${system_bashrc_runned}" ] && source /etc/bashrc
/etc/bashrc 這個文件只有在 mac 之類的系統下才有, 因此 ubuntu 這裏這行能夠不加, 不過有判斷是否存在因此加了也不要緊.
到這裏基本上就能夠比較完美的解決不通的 shell 加載順序問題了, 固然好比這個用戶用的是 zsh 之類的也須要按照類型的原理來修改.
另外, 在用戶目錄下 可能會存在 ~/.bash_profile, ~/.bash_login 這樣的文件, 但若是有這些文件 bash 就不會去載入 ~/.profile 了, 因此若是存在的話須要刪除 這些文件並把內容合併進 ~/.profile 和 ~/.bashrc 才行.
免費提供最新Linux技術教程書籍,爲開源技術愛好者努力作得更多更好:http://www.linuxprobe.com/