文章出處

今天無意發現下面這個表現:

$  env -i bash -c cd

bash: line 0: cd: HOME not set

$ env -i bash -c 'echo $HOME'

 

這表明了,Bash 只會從環境變量中繼承 HOME 變量,從來不自己初始化它?為了證實這個想法,我去翻了下源碼,發現其實并不是,在一種情況下,Bash 是會主動初始化 HOME 變量的:

if (login_shell == 1 && posixly_correct == 0)
  set_home_var ();

從這句源碼看出,Bash 只有在當前 Shell 是個登陸 Shell 且不在 Posix 模式中時,才可能去給 HOME 賦初始值。然后我就試驗了一下:

$  env -i bash --login -c 'echo $HOME'

 

握草,為什么還沒有值?遂谷歌了一下,發現 14 年有人報了個 bug https://lists.gnu.org/archive/html/bug-bash/2014-01/msg00063.html。看了這個 bug 后我明白了,原來在 Bash 內部,登陸 Shell 還分三種情況:

/* 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 變量的值分別為 1、-1、-2,但從剛才看的源碼看出,只有在 login_shell 為 1 的情況下,Bash 才會初始化 HOME 變量。那么我們再次驗證一下:

$ exec -ca -whatever bash -c 'echo $HOME'

/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


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()