環境與環境變數(the environment and environment variables)
想像你到一份新工作報到,被遞上一張寫著既定指示的小卡片:這是你的座位、這是我們說的語言、這是補給櫃的位置。這些不是你談判來的;它們在你到達前就已經設定好,而你之後也會把同一張卡片(也許略加修改)交給你雇用的任何人。程式的環境正是這張寫滿具名設定的卡片,在啟動時交給它、並被它所啟動的程式繼承。
具體來說,環境是一組具名的字串值——環境變數——作業系統在行程啟動時、連同它的命令列引數一起提供給它。每個變數就是一個名稱加一個字串值,例如 PATH=/usr/bin:/bin、HOME=/home/you 或 LANG=en_US.UTF-8。C 程式用 getenv("NAME") 讀取它們,這會回傳值字串、或在未設定時回傳 NULL;而整份清單也能透過 main 的第三個參數、或全域變數 environ 取得。關鍵行為是繼承:當一個行程啟動一個子行程時,子行程會收到父行程環境的一份副本,所以設定會沿著行程樹往下流。殼層通常是設定它們的地方——在命令前打 NAME=value、或用 export——從那之後,殼層啟動的每個程式都看得到它們。
為何重要:環境變數是一個標準、輕量的設定管道,存在於程式的程式碼與命令列之外。殼層靠它告訴程式去哪裡找可執行檔(PATH)、要用什麼語言與地區設定(LANG)、使用者的家目錄在哪裡(HOME)、以及數不清的應用程式專屬設定。因為它們會被繼承,在你殼層裡設定一次,就影響你之後執行的每個程式。一個誠實的提醒:環境只是被繼承的純文字、沒有存取控制,所以在有敵意的場合,它是放真正機密的錯誤地點——任何子行程、往往還有其他工具,都讀得到它。
在 C 程式裡,char *home = getenv("HOME"); 會給你殼層放進 HOME 變數的那段路徑字串,若未設定則為 NULL。在殼層裡執行 LANG=C ./prog,會把 LANG 變數暫時設為 C 來啟動 prog,僅限那一次執行。
getenv 讀取一個變數;子行程繼承整個環境的一份副本。
環境是被繼承、無保護的純文字——任何子行程都讀得到。它很適合放 PATH 或 LANG 這類設定,但在有敵意的場合,它並不是存放密碼或金鑰的安全保險庫。