《LINUX實戰:Bash啟動時加載配置文件過程》要點:
本文介紹了LINUX實戰:Bash啟動時加載配置文件過程,希望對您有用。如果有疑問,可以聯系我們。
本文目次:
1.1 斷定是否交互式、是否登錄式
1.2 幾種常見的bash啟動方式
1.3 加載bash情況配置文件
當用戶登錄系統時,會加載各種bash配置文件,還會設置或清空一系列變量,有時還會執行一些自界說的命令.這些行為都算是啟動bash時的過程.
另外,有些時候登錄系統是可以交互的(如正常登錄系統),有些時候是無交互的(如執行一個劇本),因此總的來說bash啟動類型可分為交互式shell和非交互式shell.更細分一層,交互式shell還分為交互式的登錄shell和交互式非登錄shell,非交互的shell在某些時候可以在bash命令后帶上"--login"或短選項"-l",這時也算是登錄式,即非交互的登錄式shell.
判斷是否為交互式shell有兩種簡單的辦法:
辦法一:判斷變量"-",如果值中含有字母"i",表示交互式.
[root@linuxidc~]# echo $- himBH [root@linuxidc~]# vim a.sh #!/bin/bash echo $- [root@linuxidc~]# bash a.sh hB
辦法二:判斷變量PS1,如果值非空,則為交互式,否則為非交互式,因為非交互式會清空該變量.
[root@linuxidc~]# echo $PS1 [\u@\h \W]\$
判斷是否為登錄式的辦法也很簡單,只需執行"shopt login"即可.值為"on"表示為登錄式,否則為非登錄式.
[root@linuxidc~]# shopt login_shell
login_shell on
[root@linuxidc~]# bash [root@linuxidc~]# shopt login_shell login_shell off
所以,要斷定是交互式以及登錄式的情況,可簡單使用如下命令:
echo $PS1;shopt login_shell
或者
echo $-;shopt login_shell
?
(1).正常登錄(偽終端登錄如ssh登錄,或虛擬終端登錄)時,為交互式登錄shell.
[root@linuxidc~]# echo $PS1;shopt login_shell [\u@\h \W]\$ login_shell on
(2).su敕令,不帶"--login"時為交互式、非登錄式shell,帶有"--login"時,為交互式、登錄式shell.
[root@linuxidc~]# su root [root@linuxidc~]# echo $PS1;shopt login_shell [\u@\h \W]\$ login_shell off
[root@linuxidc~]# su - Last login: Sat Aug 19 13:24:11 CST 2017 on pts/0 [root@linuxidc~]# echo $PS1;shopt login_shell [\u@\h \W]\$ login_shell on
(3).執行不帶"--login"選項的bash敕令時為交互式、非登錄式shell.但指定"--login"時,為交互式、登錄式shell.
[root@linuxidc~]# bash [root@linuxidc~]# echo $PS1;shopt login_shell [\u@\h \W]\$ login_shell off
[root@linuxidc~]# bash -l [root@linuxidc~]# echo $PS1;shopt login_shell [\u@\h \W]\$ login_shell on
(4).使用命令組合(使用括號包抄命令列表)以及命令替換進入子shell時,繼承父shell的交互和登錄屬性.
[root@linuxidc~]# (echo $BASH_SUBSHELL;echo $PS1;shopt login_shell) 1 [\u@\h \W]\$ login_shell on
[root@linuxidc~]# su [root@linuxidc~]# (echo $BASH_SUBSHELL;echo $PS1;shopt login_shell) 1 [\u@\h \W]\$ login_shell off
(5).ssh執行長途命令,但不登錄時,為非交互、非登錄式.
[root@linuxidc~]# ssh localhost 'echo $PS1;shopt login_shell' login_shell off
(6).執行shell劇本時,為非交互、非登錄式shell.但指定了"--login"時,將為非交互、登錄式shell.
例如,劇本內容如下:
[root@linuxidc~]# vim b.sh #!/bin/bash echo $PS1 shopt login_shell
不帶"--login"選項時,為非交互、非登錄式shell.
[root@linuxidc~]# bash b.sh login_shell off
帶"--login"選項時,為非交互、登錄式shell.
[root@linuxidc~]# bash -l b.sh login_shell on
(7).在圖形界面下打開終端時,為交互式、非登錄式shell.
?
但可以設置為使用交互式、登錄式shell.
?
?
無論是否交互、是否登錄,bash總要配置其運行環境.bash環境配置主要通過加載bash環境配置文件來完成.但是否交互、是否登錄將會影響加載哪些配置文件,除了交互、登錄屬性,有些特殊的屬性也會影響讀取配置文件的辦法.
bash環境配置文件主要有/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc和/etc/profile.d/*.sh,為了測試各種情形讀取哪些配置文件,先分別向這幾個配置文件中寫入幾個echo語句,用以斷定該配置文件是否在啟動bash時被讀取加載了.
echo "echo '/etc/profile goes'" >>/etc/_profile
echo "echo '~/.bash_profile goes'" >>~/.bash_profile
echo "echo '~/.bashrc goes'" >>~/.bashrc
echo "echo '/etc/bashrc goes'" >>/etc/bashrc
echo "echo '/etc/profile.d/test.sh goes'" >>/etc/profile.d/test.sh
chmod +x /etc/profile.d/test.sh
①.交互式登錄shell或非交互式但帶有"--login"(或短選項"-l",例如在shell劇本中指定"#!/bin/bash -l"時)的bash啟動時,將先讀取/etc/profile,再依次搜索~/.bash_profile、~/.bash_login和~/.profile,并僅加載第一個搜索到且可讀的文件.當退出時,將執行~/.bash_logout中的命令.
但要注意,在/etc/profile中有一條加載/etc/profile.d/*.sh的語句,它會使用source加載/etc/profile.d/下所有可執行的sh后綴的劇本.
[root@linuxidc~]# grep -A 8 \*\.sh /etc/profile for i in /etc/profile.d/*.sh ; do if [ -r "$i" ]; then if [ "${-#*i}" != "$-" ]; then . "$i" else . "$i" >/dev/null 2>&1 fi fi done
內層if語句中的【"${-#*i}" != "$-"】表現將"$-"從左向右模式匹配"*i"并將匹配到的內容刪除(即進行變量切分),如果"$-"切分后的值不等于"$-",則意味著是交互式shell,于是怎樣怎樣,否則怎樣怎樣.
同樣的,在~/.bash_profile中也一樣有加載~/.bashrc的敕令.
[root@linuxidc~]# grep -A 1 \~/\.bashrc ~/.bash_profile if [ -f ~/.bashrc ]; then . ~/.bashrc fi
而~/.bashrc中又有加載/etc/bashrc的敕令.
[root@linuxidc~]# grep -A 1 /etc/bashrc ~/.bashrc if [ -f /etc/bashrc ]; then . /etc/bashrc fi
其實/etc/bashrc中還有加載/etc/profile.d/*.sh的語句,但前提是非登錄式shell時才會執行.以下是部門語句:
if ! shopt -q login_shell ; then # We're not a login shell
...
for i in /etc/profile.d/*.sh; do
if [ -r "$i" ]; then
if [ "$PS1" ]; then
. "$i"
else
. "$i" >/dev/null 2>&1
fi
fi
done
...
fi
從內層if語句和/etc/profile中對應的判斷語句的作用是一致的,只不外判斷方式不同,寫法不同.
因此,交互式的登錄shell加載bash環境配置文件的實際進程如下圖:
?
以下成果驗證了結論:
Last login: Mon Aug 14 04:49:29 2017 # 新開終端登錄時
/etc/profile.d/*.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes
[root@linuxidc~]# ssh localhost # ssh遠程登錄時 root@localhost's password: Last login: Mon Aug 14 05:05:50 2017 from 172.16.10.1 /etc/profile.d/*.sh goes /etc/profile goes /etc/bashrc goes ~/.bashrc goes ~/.bash_profile goes
[root@linuxidc~]# bash -l # 執行帶有"--login"選項的login時 /etc/profile.d/*.sh goes /etc/profile goes /etc/bashrc goes ~/.bashrc goes ~/.bash_profile goes
[root@linuxidc~]# su - # su帶上"--login"時 /etc/profile.d/*.sh goes /etc/profile goes /etc/bashrc goes ~/.bashrc goes ~/.bash_profile goes
[root@linuxidc~]# vim a.sh # 執行shell腳本時帶有"--login"時 #!/bin/bash -l echo haha [root@linuxidc~]# ./a.sh /etc/profile goes /etc/bashrc goes ~/.bashrc goes ~/.bash_profile goes haha
之所以執行shell腳本時沒有顯示執行/etc/profile.d/*.sh,是因為它是非交互式的,根據/etc/profile中的【if [ "${-#*i}" != "$-" ]】判斷,它將會把/etc/profile.d/*.sh的執行結果重定向到/dev/null中.也便是說,即使是shell腳本(帶"--login "選項),它也加載了所有bash環境配置文件.
②.交互式非登錄shell的bash啟動時,將讀取~/.bashrc,不會讀取/etc/profile和~/.bash_profile、~/.bash_login和~/.profile.
因此,交互式非登錄shell加載bash環境配置文件的實際進程為下圖內方框中所示:
例如,執行不帶"--login"的bash敕令或su敕令時.
[root@linuxidc~]# bash /etc/profile.d/*.sh goes /etc/bashrc goes ~/.bashrc goes
[root@linuxidc~]# su /etc/profile.d/*.sh goes /etc/bashrc goes ~/.bashrc goes
③.非交互式、非登錄式shell啟動bash時,不會加載前面所說的任何bash環境配置文件,但會搜索變量BASH_ENV,如果搜索到了,則加載其所指定的文件.但有并非所有非交互式、非登錄式shell啟動時都邑如此,見情況④.
它就像是如許的語句:
if [ -n "$BASH_ENV" ];then . "$BASH_ENV" fi
幾乎執行所有的shell腳本都不會特意帶上"--login"選項,因此shell腳本不會加載任何bash情況配置文件,除非手動配置了變量BASH_ENV.
④.遠程shell方式啟動的bash,它雖然屬于非交互、非登錄式,但會加載~/.bashrc,所以還會加載/etc/bashrc,由于是非登錄式,所以最終還會加載/etc/profile.d/*.sh,只不外因為是非交互式而使得執行的結果全部重定向到了/dev/null中.
如果了解rsync,就知道它有一種遠程shell連接方式.所謂的遠程shell方式,是指通過網絡的方式啟動bash并將bash的尺度輸出關聯起來,就像它連接了一個遠程的shell守護進程一樣.一般由sshd實現這樣的連接方式,老版的rshd也一樣支持.
事實也確實如此,使用ssh連接但不登錄遠程主機時(例如只為了執行遠程命令),便是遠程shell的方式,但它卻是非交互、非登錄式的shell.
[root@linuxidc~]# ssh localhost echo haha root@localhost's password: /etc/bashrc goes ~/.bashrc goes haha
正如上文所說,它同樣加載了/etc/profile.d/*.sh,只不外/etc/bashrc中的if判斷語句【if [ "$PS1" ]; then】使得非交互式的shell要將執行結果重定向到/dev/null中.
本文永遠更新鏈接地址:
《LINUX實戰:Bash啟動時加載配置文件過程》是否對您有啟發,歡迎查看更多與《LINUX實戰:Bash啟動時加載配置文件過程》相關教程,學精學透。維易PHP學院為您提供精彩教程。
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/8866.html