Shell

如果程序繼承父環境,為什麼我們需要導出?

  • April 14, 2021

我在這裡讀到,在 shell中的目的export是使變數可用於從 shell 啟動的子程序。

但是,我也在這里這裡讀過“程序從其父程序(啟動它們的程序)繼承其環境”。

如果是這樣,我們為什麼需要export?我錯過了什麼?

預設情況下,shell 變數不是環境的一部分嗎?有什麼不同?

您的假設是 shell 變數在 environment 中。這是不正確的。該export命令完全定義了環境中的名稱。因此:

a=1 b=2
export b

導致目前shell知道$a擴展到 1 和$b2,但子程序將不知道任何事情,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

  1. name=val command# 命令前的賦值將該名稱導出到命令。
  2. declare/local -x name# 導出名稱,當您想避免將名稱暴露給外部範圍時,在 shell 函式中特別有用。
  3. set -a# 導出以下每個作業。

動機

那麼為什麼shell需要有自己的變數和不同的環境呢?我確信有一些歷史原因,但我認為主要原因是范圍界定。該環境適用於子程序,但是您可以在 shell 中執行許多操作,而無需分叉子程序。假設你循環:

for i in {0..50}; do
   somecommand
done

somecommand為什麼要通過包含來浪費記憶體i,使其環境比它需要的更大?如果您在 shell 中選擇的變數名恰好意味著程序不希望出現的東西怎麼辦?(我個人最喜歡的包括DEBUGVERBOSE。這些名稱隨處使用,很少有足夠的名稱空間。)

如果不是shell,環境是什麼?

有時要了解 Unix 行為,您必須查看系統呼叫,這是與核心和作業系統互動的基本 API。在這裡,我們正在查看exec呼叫系列,這是 shell 在創建子程序時使用的。這是(強調我的)手冊頁中exec(3)的引述:

execle()and函式允許呼叫者通過參數 envp 指定執行程序的execvpe()環境。envp 參數是一個指向以 null 結尾的字元串的指針數組,並且必須由 NULL 指針終止。其他函式從呼叫程序中的外部變數 environ 獲取新程序映像的環境。

因此,在 shell 中編寫export somename相當於將名稱複製到environC 中的全域字典中。但是在somename不導出它的情況下分配它就像在 C 中分配它,而不將它複製到environ變數中一樣。

引用自:https://unix.stackexchange.com/questions/130985