Linux

如何獲取systemctl啟動的程序的環境變數?

  • July 9, 2019

問題

給定systemctl如下模板和單元文件,我試圖獲取最終將在啟動時傳遞給程序的環境變數(無論服務目前是否正在執行):

/etc/systemd/system/example-template@.service

...
[Service]
Environment="VAR1=val1"
Environment="VAR2=val2"
...

/etc/systemd/system/example-template@example-unit.service.d/unit.conf

[Service]
Environment="VAR2=Overridden by %i"

在探索了所提供的選項之後,systemctl我除了 之外找不到任何東西systemctl show example-template@example-unit --property=Environment,其輸出包含作為單個字元串的變數:

Environment=VAR1=val1 VAR2=Overridden by example-unit

但是,由於它不包含方便的分隔符,我寧願避免解析它來恢復原始變數。

最初我曾考慮EnvironmentFile通過將變數移動到它們自己的文件中並從我的腳本中獲取它們來利用該指令。不幸的是,我的變數中至少有一個需要%i參數擴展,而EnvironmentFile.

有沒有更好的方法來實現我所需要的?

語境

我們有 80 個 Tomcat 實例,它們已從 OpenSUSE 伺服器遷移到 CentOS 7 伺服器。從歷史上看,這些都是通過為每個實例複製的 System V 初始化腳本來管理的。catalina.sh初始化腳本在功能上是相同的,但它們在將啟動/停止命令委託給Tomcat 附帶的腳本之前導出的值不同。更新任何常用功能都需要將更改應用到所有 80 個文件。

除此之外,我們還有一個包裝腳本,它委託給catalina.sh,添加刪除部署文件或拖尾日誌文件的選項。這是需要了解環境變數的腳本;目前,無論伺服器是否正在執行,這些都是通過使用特定參數呼叫 init 腳本來公開的。

我沒有堅持使用 System V 並將通用功能整合到單個可原始碼腳本中(我的初衷),而是決定遷移到systemd以利用其對單元文件模板的支持,因為它們似乎是在考慮這種情況下設計的。這將允許我全域定義我們的預設 Tomcat 設置,同時允許單個實例覆蓋某些變數(例如,增加 JVM 記憶體或針對新版本的 Tomcat 測試應用程序)。每個實例唯一的環境變數包括諸如 PID 文件(catalina.sh需要注意)和 Tomcat 基本(配置)位置之類的東西。

考慮到這一點,我面臨的問題是上述包裝腳本將不再有權訪問 Tomcat 實例的環境變數(例如,其中一個變數是CATALINA_HOME包含已部署應用程序、日誌和配置文件的路徑用於伺服器)。腳本的某些功能不需要伺服器正在執行(例如清理停止的伺服器),因此從程序中獲取環境是不可行的。

現在我可以讓包裝腳本從單元名稱中派生(猜測)這些資訊,或者通過讓包裝腳本直接呼叫腳本來完全放棄將 Tomcat 伺服器作為服務執行catalina.sh;但是我希望有關服務的唯一資訊來源是服務本身,並且還能夠利用一些功能,systemd例如在服務進入失敗狀態時自動重新啟動服務。

版本資訊

  • CentOS Linux 版本 7.6.1810
  • 系統 219
  • bash 4.2.46(2)-發布

我最近完成了這樣的遷移。

適用於所有單元的預設值在模板文件中的 Environment= 指令中。EnvironmentFile=production.%i.env 用於載入每個實例的覆蓋。

不要擔心你不能在 production.foo.env 中使用 %i。只需在該文件中硬編碼“foo”即可。如果需要,這可以自動化。

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