bash的配置文件(linux學習之八)

一、什麼是shell


廣義的shell指的是,能夠操作應用程序的接口都稱爲shell,(包括linux和windows的圖形界面)

狹義的shell是指,命令行方面的程序,包括zsh,bash,csh,等等


怎樣查看當前系統的可用shell呢?

文件/etc/shells 中所列的shell,稱爲當前系統上安全的shell列表。默認shell如果不是文件/etc/shells中的shell,很可能拒絕用戶登入系統。


#

[root@localhost ~]# cat /etc/shells 
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh


爲甚麼/etc/shells 文件中的shell列表稱爲合法的shell列表,這是因爲系統某些服務在運行的時候,會去檢查用戶能夠使用的shells,而檢查的標準就是根據/etc/shells 文件中的shell列表。


二、bash命令與sh命令的區別


Linux 操作系統缺省的 shell 是Bourne Again shell,它是 Bourne shell 的擴展,簡稱 Bash,與 Bourne shell 完全向後兼容,並且在Bourne shell 的基礎上增加、增強了很多特性。


GNU/Linux 操作系統中的 /bin/sh 本是 bash (Bourne-Again Shell) 的符號鏈接,但鑑於 bash 過於複雜,有人把 ash 從 NetBSD 移植到 Linux 並更名爲 dash (Debian Almquist Shell),並建議將 /bin/sh 指向它,以獲得更快的腳本執行速度。Dash Shell 比 Bash Shell 小的多,符合POSIX標準。


debian和Ubuntu中,/bin/sh默認已經指向dash,這是一個不同於bash的shell,它主要是爲了執行腳本而出現,而不是交互,它速度更快,但功能相比bash要少很多,語法嚴格遵守POSIX標準。


三、bash的四種模式


在man bash的INVOCATION一節講述了bash的四種模式,bash會依據這四種模式而選擇加載不同的配置文件,而且加載的順序也有所不同。


Bash是shell的一種,運行中的Bash有兩種屬性(狀態/模式),一種,是否interactive shell(交互式Shell),另一種,是否login shell(登錄Shell)。兩種組合成四種模式。


  • login shell(登入式shell):


定義:A login shell is one whose first character of argument zero is a -, or one started with the --login option.


大概意思是:一個登入式shell,它的第零個參數的第一個字符是  -,或者 它是一個以 --login 選項啓動的shell。


解釋一下這個定義


1、第零個參數的第一個字符是 - 的shell是登入式shell


比如: tty1-tty6 終端登入系統(系統默認shell是bash)是登入式shell

tty1-tty6 登入系統後


#

dayun@c:~$ echo $0
-bash


第零個參數的第一個字符是 -,所以這是一個登入式shell。


2、以 --login 選項啓動的bash是登入式shell

比如:bash --login[-l]

系統登入以後,在當前shell中登入子shell時,加上--login選項,表示登入的這個子shell是登入式shell


此外。除定義外,我們判斷這兩種模式的方法。


登入式shell與非登入式shell的區別我們可以從字面上理解,登入式shell要求用戶輸入用戶名,密碼。包含登入一個shell的全過程。(這個說法不一定嚴謹準確,比如bash --login[- l]  這種方式就不需要輸入用戶名密碼,因爲它登入的是當前shell的子shell,用戶名,密碼與當前shell相同,所以省去)


登入式shell和非登入式shell的退出機制不同。

非登入式shell,退出時,使用exit命令退出,不能使用logout命令退出


#

cluster@c:~$ bash   #運行bash命令,進入當前shell的子shell(非登入式shell)
cluster@c:~$ logout  #運行login命令
bash: logout: not login shell: use `exit'  #報錯,因爲是非登入式shell,不能用login退出
cluster@c:~$ exit   #使用exit命令
exit
cluster@c:~$        #成功退出


登入式shell,退出時,使用logout命令退出,能夠使用exit命令退出,但是此時的exit命令扔是調用logout命令。


#

#登入式shell使用logout命令正常退出

cluster@c:~$ bash -l
cluster@c:~$ logout 
cluster@c:~$ 


#登入式shell使用exit命令,通過調用logout命令,也能退出

cluster@c:~$ bash -l
cluster@c:~$ exit
logout
cluster@c:~$


常見的login shell與no-login shell


tty1-tty6直接登入的shell爲login shell。                              

su -[l] UserName爲登入式shell 如果不帶有-或-l選項的爲no-login shell

ssh UserName@HostName 通過ssh登入shell爲登入式shell。ssh UserName@HostName "command"爲非登入式shell                                  

bash --login[-l]爲登入式shell,沒有--login或-l選項的爲非登入式shell,以下相同。

su -[l] UserName -c "command"

bash --login[-l] -c "command"

bash -l[--login] script.sh

你以 X window 登陸 Linux 後, 再以 X 的圖形化接口啓動終端機


  • interactive shell(交互式shell):


定義:An  interactive  shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option.  PS1 is set and $- includes  i  if  bash  is interactive, allowing a shell script or a startup file to test this state.


大概意思是:不帶有非選項參數,且沒有-c選項,它的標準輸入與標準輸出直接與終端相連的的shell是交互式shell,或者有-i選項的也是交互式shell。交互式shell他的PS1一般被設置,並且變量$-包含i


解釋一下這個定義


1、不帶有非選項參數,且沒有-c選項,它的標準輸入與標準輸出直接與終端相連的的shell是交互式shell。


什麼是非選項參數,bash /path/to/script.sh 中的/path/to/script.sh就是非選項參數,像-c,-i,-l,--login等都是選項參數。例子中帶有非選項參數,所以他不是交互式shell。像su -[l] UserName -c "command",bash --login[-l] -c "command"這種帶有-c選項的也不是交互式shell。


2、有-i選項的也是交互式shell


命令中有-i選項的就是交互式shell,比如 bash -i /path/to/script.sh,等等


3、我沒按照字面意思也能大概判斷。交互式shell就是能夠在當前shell下輸入,輸出(一般帶有-i選項的執行腳本,或帶有-i -c 選項執行命令的也是交互式shell,他們是指在其他shell執行,然後退出shell,把結果返回到當前shell)


4、交互式shell,通過執行命令 echo $- 返回值一般有i


四、種模式配置文件文件加載過程


配置文件的作用: 持久保存用戶的配置,只在登入時讀取一次


運行中的Shell排列組合有這麼幾種


  • 登錄交互式Shell

  • 登錄非交互式Shell


這兩種模式,加載配置文件的順序和過程相同

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


copy 鳥哥私房菜的一段,寫得挺清楚


bash 在讀完了整體環境設定的 /etc/profile 並藉此調用其他配置文件後,接下來則是會讀取使用戶的個人配置文件。 在 login shell 的 bash 環境中,所讀取得個人偏好配置文件其實主要有三個,依序分別是:

1. ~/.bash_profile

2. ~/.bash_login

3. ~/.profile

其實 bash 的 login shell 設定只會讀取上面三個文件中的一個,讀取的順序是按照上面的順序。


也就是說,如果~/.bash_profile存在,其他兩個文件無論是否存在,都不會被讀取如果~/.bash_profile不存在纔會讀取~/.bash_login,而前兩者都不存在纔會讀取~/.profile 


  • 非登錄交互式Shell

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.


上述的英文解釋,是在centos系統上bash幫助手冊上的一段,而在ubuntu系統上會有稍微不同,ubuntu系統


ubuntu系統上的描述


 When  an  interactive  shell  that  is  not  a  login  shell  is started, bash reads and executes commands from /etc/bash.bashrc and~/.bashrc, if these files exist.


ubuntu系統上非登入交互式shell,啓動時會主動讀取/etc/bash.bashrc and~/.bashrc兩個文件。


centos系統上非登入交互式shell,啓動時只會主動讀取~/.bashrc ,但是在~/.bashrc中有一段命令


#

if [ -f /etc/bashrc ]; then  #如果存在/etc/bashrc
        . /etc/bashrc        #則會調用/etc/bashrc
fi


我們可以看出centos系統中的/etc/bashrc 功能和ubuntu系統中的/etc/bash.bashrc一樣。


  • 非登錄非交互式Shell

When bash is started non-interactively, to run a shell script, for example, it looks  for  the  variable  BASH_ENV  in  the  environment, expands  its  value  if  it appears there, and uses the expanded value as the name of a file to read and execute.  Bash behaves as if the following command were executed:

if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

but the value of the PATH variable is not used to search for the file name.


非登入非交互式shell,那個文件也不會調用,但是,如果環境變量BASH_ENV存在,則會調用變量BASH_ENV所指代的文件。


但是,在測試時,非登錄非交互式Shell加載 BASH_ENV變量測試過程中有點問題問題鏈接 。有知道原因的請賜教。


手動讀取配置文件


#

source /etc/profile  #或者下面這種方式

. /etc/profile





六、補充一下,以其他用戶運行command命令時,是否加-或-l 選項 ,環境變量加載都不成功得原因


以下是好久之前網上的找的,沒有原文章鏈接。


 sudo command

   sudo命令是以root的身份執行command命令,但是環境變量還是當前用戶的,執行目錄也仍然是當前目錄

  即環境變量和執行目錄都不會切換到root

sudo command1 | command2     這種命令只會是command1有root權限,但是管道符後面的command則還是沒有root權限。Sudo只會提升緊跟其後的那個命令的權限

 

 su - username -c "command1;command2"

  su命令是切換到另一個用戶,環境變量會切換到username,執行目錄會切換到目標用戶username的家目錄

  提醒:

   假設當前用戶爲普通用戶lx(該用戶沒有ORACLE_SID這個環境變量),以lx用戶執行命令

   su - oracle -c "echo $ORACLE_SID"

   輸出會是空

   su - username -c環境變量會切換到username,爲什麼沒打印出oracle用戶的ORACLE_SID環境變量呢?

   因爲雙引號是不屏蔽$這個特殊字符的,在執行su - oracle -c "echo $ORACLE_SID"命令,

   將先在當前用戶下替換變量ORACLE_SID(當前用戶的ORACLE_SID變量爲空),然後發送給oracle執行的命令就成了 echo ""

   

   我們的意圖是將echo $ORACLE_SID這個命令發送給oracle用戶,打印出oracle用戶用戶的環境變量ORACLE_SID,有以下解決方式:


   1、su - oracle -c 'echo $ORACLE_SID'   (單引號會屏蔽所有的特殊字符)

   2、su - oracle -c "echo \$ORACLE_SID"


命令行命令“

 su 與 su - 命令的卻別:

  su 命令僅切換用戶身份,例如從A切換到B,執行whoami命令,顯示的是用戶B,但當前目錄不會切換,

  環境變量也仍未切換,仍爲A用戶的環境變量

  

  su - 命令切換用戶,A切換到B,會以登錄B的流程執行,不僅會切換用戶還會執行.profile文件,

  更換成B用戶的環境變量,目錄切換到B的家目錄



參考:man bash 的幫助文檔,鳥哥linux私房菜

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章