今天無心發現下面這個表現:html
$ env -i bash -c cdshell bash: line 0: cd: HOME not setbash $ env -i bash -c 'echo $HOME'函數
|
這代表了,Bash 只會從環境變量中繼承 HOME 變量,歷來不本身初始化它?爲了證明這個想法,我去翻了下源碼,發現其實並非,在一種狀況下,Bash 是會主動初始化 HOME 變量的:ui
if (login_shell == 1 && posixly_correct == 0) set_home_var ();
從這句源碼看出,Bash 只有在當前 Shell 是個登錄 Shell 且不在 Posix 模式中時,纔可能去給 HOME 賦初始值。而後我就試驗了一下:this
$ env -i bash --login -c 'echo $HOME'spa
|
握草,爲何尚未值?遂谷歌了一下,發現 14 年有人報了個 bug https://lists.gnu.org/archive/html/bug-bash/2014-01/msg00063.html。看了這個 bug 後我明白了,原來在 Bash 內部,登錄 Shell 還分三種狀況:code
/* Non-zero means that this shell is a login shell. Specifically: 0 = not login shell. 1 = login shell from getty (or equivalent fake out) -1 = login shell from "--login" (or -l) flag. -2 = both from getty, and from flag. */ int login_shell = 0;
一種是 Bash 的父進程啓動 Bash 時傳入的第 0 個參數(經過 exec* 函數指定)的第一個字符是以 - 開頭的狀況,一種是 Bash 啓動時用了 --login 或 -l 選項的狀況,最後一種是上面兩種表現混合的狀況,login_shell 變量的值分別爲 一、-一、-2,但從剛纔看的源碼看出,只有在 login_shell 爲 1 的狀況下,Bash 纔會初始化 HOME 變量。那麼咱們再次驗證一下:htm
$ exec -ca -whatever bash -c 'echo $HOME'blog /home/admin |
這條命令用到了 exec 的 -a 選項來指定 argv[0]。咱們還能夠本身寫個 c 程序驗證一下:
$ cat a.c #include<unistd.h> int main() { char *argv[ ] = { "-whatever", "-c", "echo $HOME", NULL }; char *envp[ ] = { NULL }; execve("/bin/bash", argv, envp); } $ gcc a.c -o a $ ./a /home/admin |