问题
给定systemctl
如下模板和单元文件,我试图获取最终将在启动时传递给进程的环境变量(无论服务当前是否正在运行):
/etc/systemd/system/[email protected]
...
[Service]
Environment="VAR1=val1"
Environment="VAR2=val2"
...
/etc/systemd/system/[email protected]/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)-发布
答案1
我最近完成了这样的迁移。
适用于所有单元的默认值位于模板文件中的 Environment= 指令中。 EnvironmentFile=production.%i.env 用于加载每个实例的覆盖。
不要担心你不能在 production.foo.env 中使用 %i。只需在该文件中硬编码“foo”即可。如果需要的话,这可以自动化。