Shell

設置環境變數的最佳發行版/外殼無關方式是什麼?

  • October 7, 2020

這個問題說明了一切。我目前使用 Arch Linux 和 zsh,但我想要一個(至少)在 VT 和 xterms 上都可以工作的解決方案,並且(希望,最好)如果我切換發行版或 shell 將繼續工作。

我在不同發行版的文件中聽到了對這個問題的截然不同的答案。Ubuntu 說“使用 .pam_environment”。我認為在 Arch 中他們推薦的內容取決於你的 shell。目前,我將所有內容都放在.profile中,如果 shell 由於某種原因(例如,如果 .bash_profile 存在,則為 bash),我會通過手動獲取它來覆蓋它。但似乎必須有更好的方法。

不幸的是,沒有完全可移植的位置來設置環境變數。最接近的兩個文件是~/.profile,這是傳統位置,可以在許多設置中開箱即用,以及**~/.pam_environment**,一個現代、普通但有限的替代方案。

放什麼~/.pam_environment

所有使用PAM並啟用此文件~/.pam_environment的登錄方法都會讀取該文件。這涵蓋了當今大多數 Linux 系統。

的主要優點~/.pam_environment是(啟用時)它在使用者的 shell 啟動之前被讀取,因此無論會話類型、登錄 shell 和其他復雜性如何,它都可以工作。它甚至適用於非互動式登錄,例如su -c somecommandssh somecommand

的主要限制~/.pam_environment是你只能在那裡放置簡單的賦值,而不是複雜的 shell 語法。該文件的語法如下。

  • 文件被逐行解析。
  • 每行必須具有VAR=VALUEVAR 由字母、數字和下劃線組成的形式。另一種形式VAR DEFAULT=value允許使用${VAR}語法和特殊變數@{HOME}@{SHELL}.
  • #開始註釋,它不能出現在值中。
  • 如果 VALUE 被 包圍",則 VAR 設置為引號之間的字元串。
  • \$\@插入文字$@長行可以通過用 . 轉義換行符來拆分\
  • 如果存在語法錯誤,例如沒有=空格或未加引號的空格,則會從環境中刪除該變數。

所以從好的方面來說,它~/.pam_environment可以在很多情況下工作。不利的一面是,您不能使用命令的輸出(例如,測試目錄或程序是否存在),並且某些字元(#"、換行符)是不可能或很麻煩的。

放什麼~/.profile

此文件應具有可移植 (POSIX) sh 語法。[[ … ]]如果您知道您的系統將這些 shell作為/bin/sh.

該文件可能會被自動化應用程序中的腳本讀取,因此它不應呼叫產生任何輸出的程序或呼叫exec. 如果您想在文本模式登錄上執行此操作,請僅對互動式 shell 執行此操作。例子:

case $- in *i*)
 # Display a message if I have new mail
 if mail -e; then echo 'You have new mail'; fi
 # If zsh is available, and this looks like a text-mode login, run zsh
 case "`ps $PPID` " in
   *" login "*)
     if type zsh >/dev/null 2>/dev/null; then exec zsh; fi;;
 esac
esac

這是一個使用/bin/sh你的登錄 shell 並切換到你最喜歡的 shell 的例子。另請參閱當我的系統管理員拒絕讓我更改它時,我如何使用 bash 作為我的登錄 shell

~/.profile非圖形登錄何時不讀取?

不同的登錄 shell讀取不同的文件。

如果您的登錄 shell 是 bash

Bash 讀取~/.bash_login或者~/.bash_profile如果它們存在而不是~/.profile. ~/.bashrc即使它是互動式的,bash 也不會在登錄 shell 中讀取。要永遠不必再記住這些怪癖,請~/.bash_profile使用以下兩行創建一個:

. ~/.profile
case $- in *i*) . ~/.bashrc;; esac

另請參閱哪些設置文件應該用於使用 bash 設置環境變數?

如果您的登錄 shell 是 zsh

Zsh 讀取~/.zprofileand ~/.zlogin,但不是~/.profile. Zsh 的語法與 sh 不同,但可以~/.profile在 sh 仿真模式下讀取。您可以將其用於您的~/.zprofile

emulate sh -c '. ~/.profile'

另請參閱Zsh 未命中 ~/.profile

如果您的登錄外殼是其他外殼

/bin/sh除了用作您的登錄 shell 和您最喜歡的 shell(如fish)僅用作互動式 shell 之外,您無能為力。這就是我對 zsh 所做的。有關從~/.profile.

遠端命令

在不通過互動式 shell 的情況下呼叫遠端命令時,並非所有 shell 都會讀取啟動文件。

Ksh 讀取由ENV變數指定的文件,如果你設法通過它。

Bash 讀取~/.bashrc它是否不是互動式的 (!) 並且它的父程序被稱為rshdor sshd。所以你可以開始你~/.bashrc

if [[ $- != *i* ]]; then
 . ~/.profile
 return
fi

Zsh 總是~/.zshenv在啟動時讀取。請謹慎使用,因為 zsh 的每個實例都會讀取它,即使它是您設置了其他變數的子 shell。如果 zsh 是您的登錄 shell,並且您想使用它為遠端命令設置變數,請使用保護:在 中設置一些變數~/.profile,例如MY_ENVIRONMENT_HAS_BEEN_SET=yes,並在閱讀之前檢查此保護~/.profile

if [[ -z $MY_ENVIRONMENT_HAS_BEEN_SET ]]; then emulate sh -c '~/.profile'; fi

圖形登錄的案例

許多發行版、顯示管理器和桌面環境都安排執行~/.profile,或者通過從啟動腳本中顯式獲取它,或者通過執行登錄 shell。

不幸的是,沒有通用的方法來處理~/.profile未讀取的發行版/DM/DE 組合。

如果您使用由 啟動的傳統會話~/.xsession,則應在此處設置環境變數;通過採購~/.profile(即. ~/.profile)來做到這一點。請注意,在某些設置中,桌面環境啟動腳本將~/.profile再次獲取源。

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