讓systemd服務繼承/etc/profile.d中的環境變數

讓systemd服務繼承/etc/profile.d中的環境變數

我有一個systemd服務在特定用戶下運行。

我錯誤地認為該服務可以訪問所有用戶從腳本/導出繼承的環境變量/etc/profile.d

systemd有沒有一種方法可以完成此任務,而無需手動複製單元檔案定義中的變數。

例如,我有以下內容

$ cat /etc/profile.d/somexports

export VAR1=VALUE1
export VAR2=VALUE2

這可以傳遞/匯出到systemd服務嗎?

答案1

有幾種可能的環境來源:

  1. 使用Environment=它可以設定變數
  2. 使用EnvironmentFile=它可以從文件加載值
  3. 使用PassEnvironment=它可以讓您定義應從 PID1 傳遞的變數。
  4. 靜態配置(例如$USER

這聽起來可能EnvironmentFile=/etc/profile.d/someexports就是您想要的,但事實並非如此。 /etc/profile.d/*通常由您的 shell 取得並且​​可以由您的 shell 進行解析。 systemd與 shell 無關,因此它不會依賴 bash 語法。應該EnvironmentFile包含更嚴格的換行符號分隔的變數賦值。

systemd的設計不鼓勵動態改變單元或其環境。甚至這個EnvironmentFile=選項也是迫於壓力才添加的,後來被systemd開發者認為是錯誤。這種設計的一個例子是,它$PATH不會影響使用哪些二進位。這使事情更具確定性,因為當您定義一個單元時,您正在定義有關該單元應如何運行的所有內容,而無需擔心外部影響。

所以簡短的回答是:/etc/profile.d/*systemd

但您可能想要的答案是:是的,您可以加載它。您只需要透過 shell 運行您的應用程式。

您可以透過更改來做到這一點:

ExecStart=/usr/bin/myservice

ExecStart=/usr/bin/bash -lc myservice

這將導致bash成為父進程,載入/etc/profile.d/該環境並將其轉發給其子進程。另請注意,我沒有指定 的完整絕對路徑myservice。在這種情況下,myservice將基於$PATH並且可能是也可能不是/usr/bin/myservice。您可以看到這可能會使故障排除變得更加困難,而這正是採用此方法的缺點。

答案2

我認為這個問題可以解決如下

ExecStart=/bin/sh -lc /path/to/binary

-l標誌使 shell 呼叫成為登入 shell。我們需要這個,因為只有登入 shell 來源設定檔腳本。

$ bash --help | grep -- -l
GNU bash, version 4.4.12(1)-release-(x86_64-pc-linux-gnu)
    --login

相關內容