如果程序繼承父環境,為什麼我們需要導出?
我在這裡讀到,在 shell中的目的
export
是使變數可用於從 shell 啟動的子程序。但是,我也在這里和這裡讀過“程序從其父程序(啟動它們的程序)繼承其環境”。
如果是這樣,我們為什麼需要
export
?我錯過了什麼?預設情況下,shell 變數不是環境的一部分嗎?有什麼不同?
您的假設是 shell 變數在 environment 中。這是不正確的。該
export
命令完全定義了環境中的名稱。因此:a=1 b=2 export b
導致目前shell知道
$a
擴展到 1 和$b
2,但子程序將不知道任何事情,a
因為它不是環境的一部分(即使在目前 shell 中)。一些有用的工具:
set
: 用於查看目前 shell 的參數,導出或不導出set -k
:在環境中設置分配的參數。考慮f() { set -k; env; }; f a=1
set -a
: 告訴 shell 將設置的任何名稱放入環境中。export
就像在每項作業之前都放一樣。.env
對文件很有用,如set -a; . .env; set +a
.export
: 告訴 shell 在環境中放置一個名稱。導出和賦值是兩個完全不同的操作。env
: 作為一個外部命令,env
只能告訴你繼承的環境,因此,它對健全性檢查很有用。env -i
: 用於在啟動子程序之前清除環境。替代品
export
:
name=val command
# 命令前的賦值將該名稱導出到命令。declare/local -x name
# 導出名稱,當您想避免將名稱暴露給外部範圍時,在 shell 函式中特別有用。set -a
# 導出以下每個作業。動機
那麼為什麼shell需要有自己的變數和不同的環境呢?我確信有一些歷史原因,但我認為主要原因是范圍界定。該環境適用於子程序,但是您可以在 shell 中執行許多操作,而無需分叉子程序。假設你循環:
for i in {0..50}; do somecommand done
somecommand
為什麼要通過包含來浪費記憶體i
,使其環境比它需要的更大?如果您在 shell 中選擇的變數名恰好意味著程序不希望出現的東西怎麼辦?(我個人最喜歡的包括DEBUG
和VERBOSE
。這些名稱隨處使用,很少有足夠的名稱空間。)如果不是shell,環境是什麼?
有時要了解 Unix 行為,您必須查看系統呼叫,這是與核心和作業系統互動的基本 API。在這裡,我們正在查看
exec
呼叫系列,這是 shell 在創建子程序時使用的。這是(強調我的)手冊頁中exec(3)
的引述:
execle()
and函式允許呼叫者通過參數 envp 指定執行程序的execvpe()
環境。envp 參數是一個指向以 null 結尾的字元串的指針數組,並且必須由 NULL 指針終止。其他函式從呼叫程序中的外部變數 environ 獲取新程序映像的環境。因此,在 shell 中編寫
export somename
相當於將名稱複製到environ
C 中的全域字典中。但是在somename
不導出它的情況下分配它就像在 C 中分配它,而不將它複製到environ
變數中一樣。