1. 程式人生 > >由開啟coredump引起的對shell的深入探究

由開啟coredump引起的對shell的深入探究

    問題:要開coredump功能,需要把core file size的軟限制值由0改為一個大於0的值,一般取unlimited。

    有兩個方法可以改變這個值,一個是ulimit命令,執行ulimit –c unlimited,可把core file size值設定為unlimited,但這隻對當前shell有效;另一個是修改/etc/security/limits.conf檔案,在該檔案中加入如下格式的一句話:

<domain>  <type> <item>  <value>

如,

win7  soft  core  unlimited

這樣,當win7使用者開啟shell時,其core file size 值會自動設定為unlimited。如果把win7換成*,則以上配置對所有使用者有效。

     我們有一個程式要開機執行,因此把/home/root/tss256 放在rc.local中,開機後會自動執行該程式。在實驗過程中,該程序會突然退出,為了方便查詢原因,我們選擇使用coredump技術來儲存程序退出時的記憶體狀態。

     如果採用改變limits.conf檔案的方法,rc.local執行時,其執行環境是shell麼?如果是,是哪個使用者開啟的shell呢?

 一,rc.local執行時的執行環境是 shell麼?

 1,什麼是shell呢?

     shell是一個程式,常用的shell是Bash shell,程式為/bin/bash。shell讀取使用者輸入的命令,並執行相應的應用程式以響應命令(由環境變數PATH決定搜尋應用程式的路徑),因此,我們可以把shell理解為一種命令直譯器,或者一種類似vs2008的開發環境。

     當一個shell啟動時,系統會根據不同的啟動方式判斷shell型別,並讀取不同的配置檔案(見下文),並根據這些配置檔案為將要啟動的shell配置環境變數(不同的配置檔案導致不同的環境變數)。

     環境變數用於描述當下的shell環境。比如,USER表示當前shell所屬的使用者,$表示當前shell的PID號,PPID表示當前shell的父程序的PID號,SHELL表示當前shell是執行的哪個程式(因為shell也是一個程式,一般為/bin/bash),HISTSIZE表示當前shell可以儲存的歷史命令的最大個數。(參考《鳥哥私房菜》)。用printenv命令可以列印全部的環境變數。

     因此,判斷rc.local裡內容執行時是否是在一個shell中執行,只需在rc.local中檢視SHELL變數的值即可,在rc.local中加入echo $SHELL。

     經驗證,rc.local中,SHELL=/bin/bash,因此rc.local是在bash shell環境中執行的。

     然而,這跟我們平時對shell的印象不太一樣,平時啟動shell時都是通過某個使用者登入linux後,然後右擊桌面,選擇開啟終端,這就是一個shell,又或者通過ssh,輸入使用者名稱和密碼遠端登入Linux,啟動的就是一個shell。很明顯,rc.local的執行跟我們印象中的shell不一樣。

2,shell的型別有哪些呢?

     shell按照登入與否,可分為登入式shell和非登入式shell;按照能否與使用者互動與否,可分為互動式shell和非互動式shell。

(1)登入式shell

輸入使用者名稱和密碼後,啟動的shell就是登入式shell,比如sshd遠端登入,又比如在本地Linux登入介面輸入使用者名稱密碼登入。

(2)非登入式shell

     與登入式shell相比,它不需要輸入使用者名稱密碼即可啟動。其一般是在shell中輸入bash命令,或者本地登入Linux登入介面後,右鍵桌面->開啟終端開啟的shell。

登陸式shell和非登陸式shell啟動時讀取的配置檔案不太一樣。登入式shell啟動時,系統會按照以下順序讀取配置檔案,並進行相應的設定。

Ø  /etc/passwd

     系統會據此判斷系統上是否有輸入的使用者名稱,如果有,則獲取其UID,GID,以及將要啟動的shell是哪個程式。下面內容擷取自/etc/passwd:

                                                      root:x:0:0:root:/root:/bin/bash

                                                      win7:x:500:500:win7:/home/win7:/bin/bash

      第一句表示,系統有root這個使用者,其密碼用x表示,UID為0,GID為0,全名為root,家目錄(即執行cd命令時進入的目錄)為/root,啟動的shell程式為/bin/bash程式。

      第二句表示,系統有win7這個使用者,其密碼用x表示,UID和GID均為500,家目錄為/home/win7,啟動的shell程式為/bin/bash程式。

Ø  /etc/shadow

       該檔案記錄的每個使用者的密碼,下面內容擷取自該檔案:

      root:$6$H/KS4EYo0ZSZmTC8$xTMs4cAeWbQkpzHT8lB/75qerzpWlvxsF6XW9JwVzJyHEDiKcCdKu7cooUrut5NUE1wa1drb9C8KXiGXAPY021:17238:0:99999:7:::

     win7:$6$y1OyG8nlGdeqeao0$iPKvObi273nm5/9krOp9CMOhj7Ngux/9gPbj/5bLw24p7rgjzm4StLDu/.3lVewgGFmdP2Za/fvYeIFSgXsQx0:17238:0:99999:7:::

     上文中使用者名稱後面那串字元即是密碼,顯然已經加密。在/etc/passwd中檢查到使用者存在後,系統會判斷輸入的密碼與記錄的密碼是否一致。

Ø  /etc/profile

       系統為使用者啟動相應的shell程式(一般為/bin/bash)後,會自動讀取該檔案,並設定以下環境變數(export命令使自定義變數變為環境變數):

       export PATH USER LOGNAME MAILHOSTNAME HISTSIZE HISTCONTROL

Ø  $HOME/.bash_profile

       此處,$HOME表示家目錄,在/etc/passwd中得到。注意,不同使用者的家目錄不一樣,這就實現了不同使用者可以配置不同的shell環境變數。

       在該檔案中,要執行./.bashrc。

Ø  $HOME/.bashrc

       該檔案中執行/etc/bashrc

Ø  /etc/bashrc

       該檔案會對PROMPT_COMMAND變數、PATH變數、umask值進行設定。

       注意:由pstree –npu命令可知,從/etc/profile至/etc/bashrc六個檔案的許可權均為:

-rw-r--r—

       也就是說,這些檔案並非shell指令碼,都是在系統為使用者啟動相應的shell後,系統自動讀取並使其生效的檔案。猜測,類似於在該shell中執行:

              source/etc/profile

              source$HOME/.bash_profile

              source$HOME/.bashrc

              source/etc/bashrc

互動式shell只生效上述的$HOME/.bashrc、/etc/bashrc檔案。可以在以上5個檔案中加入列印資訊,分別啟動登陸式shell和非登陸式shell,即可得知該結論。

(3)互動式shell

     顧名思義,互動式shell能與使用者進行互動,使用者在輸入命令,shell會執行該命令並返回執行結果,我們用的shell一般都是這種型別。

(4)非互動式shell

     與互動式shell相反,其不能與使用者進行互動,其實際是執行中的shell指令碼。

     綜上所述,rc.local是一個shell指令碼,其執行環境是一個非登入式非互動式shell。

     其實,還可以從另一個角度得出以上判斷,那就是shell指令碼的第一行必須寫這句話:

                                                     #!/bin/bash

在shell指令碼中,這一行的“#”並非註釋的意思,而是告訴系統執行該指令碼時應該呼叫/bin/bash程式,即選擇bash shell作為該指令碼的執行環境。開啟rc.local,第一句就是#!/bin/bash,因此可以判斷rc.local是一個shell指令碼。

       二,該shell的所屬的使用者是誰

       為了知道該shell的使用者,我們在rc.local中加入echo $USER命令,但結果顯示為空,即該shell環境中沒有這個變數。因此,這個shell環境不屬於任何使用者。

       其實通過推理也可以得出這個結論,因為執行rc.local時還沒有使用者進行登入。

       既然rc.local執行時,其shell環境沒有使用者,因此,通過改變limits.conf來設定core file size 值的方法不可行。只能在rc.local中加入命令ulimit -c unlimited。然而,為什麼在登陸式互動式shell中,即ssh登陸或者本機登陸Linux系統後,檢視ulimit –a ,core file size值依然為0呢?這是因為ulimit 只能改變當前shell環境中的值,雖然rc.local這個非互動式shell並沒有停止執行,但其與當前的shell是兩個不同的環境