我有一個systemd
服務在特定用戶下運行。
我錯誤地認為該服務可以訪問所有用戶從腳本/導出繼承的環境變量/etc/profile.d
systemd
有沒有一種方法可以完成此任務,而無需手動複製單元檔案定義中的變數。
例如,我有以下內容
$ cat /etc/profile.d/somexports
export VAR1=VALUE1
export VAR2=VALUE2
這可以傳遞/匯出到systemd
服務嗎?
答案1
有幾種可能的環境來源:
- 使用
Environment=
它可以設定變數 - 使用
EnvironmentFile=
它可以從文件加載值 - 使用
PassEnvironment=
它可以讓您定義應從 PID1 傳遞的變數。 - 靜態配置(例如
$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