![如何在 systemd 单元文件中指定动态“环境”变量?](https://linux22.com/image/229716/%E5%A6%82%E4%BD%95%E5%9C%A8%20systemd%20%E5%8D%95%E5%85%83%E6%96%87%E4%BB%B6%E4%B8%AD%E6%8C%87%E5%AE%9A%E5%8A%A8%E6%80%81%E2%80%9C%E7%8E%AF%E5%A2%83%E2%80%9D%E5%8F%98%E9%87%8F%EF%BC%9F.png)
这$(ls -d...)
在 systemd 单元文件中不起作用:
[Service]
Type=forking
Environment="ORACLE_HOME=$(ls -d /usr/lib/oracle/*/client64 | sort -rV | head -n1)"
Environment="TNS_ADMIN=$(ls -d /usr/lib/oracle/*/client64/lib/network/admin | sort -rV | head -n1)"
我想避免对 Oracle 客户端版本(目前为 19.19)进行硬编码,以简化更新。当我安装新的 Oracle 客户端时,我不想修改 systemd 单元文件。
我怎样才能做到这一点?如果重要的话我使用 RHEL9。
答案1
最常见的方法:
使用
EnvironmentFile=
它是动态生成的,例如通过 ExecStartPre= 调用一个简单的脚本。当前的 systemd 版本将在每次执行之前重新读取 EnvironmentFile 以允许其工作。 (/run 是存放临时文件的好位置。)这是最简单的方法,因为脚本只需要写出这些
KEY="value"
行。使用系统发电机每次(重新)加载配置时,它都会在 /run/systemd 动态写入单元文件。生成器可以是 shell 脚本,只要它仅限于本地文件系统访问。
发电机可以放置在
/etc/systemd/system-generators/
;它们将在每次启动和每次“systemctl daemon-reload”期间运行,获取输出路径为$1
.它们实际上会在任何单元启动之前运行,因此它们不能期望网络或其他任何东西都会启动。这是最灵活的方法,因为任何单位选项都可以动态指定 - 不仅是环境,还包括其他内容,例如WorkingDirectory=。 (生成器不需要创建所有的单元;它可以通过创建或类似的方式以通常的方式扩展现有单元
$1/oracle.service.d/environ.conf
。)
其他方法:
使用实例化服务单元
[email protected]
用于%i
填写版本。您仍然需要禁用“oracle@old”并启用“oracle@new”,但它可以节省您打开文本编辑器的时间。 (而且它还可以通过启动正确的单元轻松快速回滚到旧版本。)思考您可以拥有一个Alias=oracle.service
,以便启用实例会自动将其映射到较短的名称。使用包装 shell 脚本来设置变量并
exec
保存实际程序。是的,这exec
很重要。 (另外,使用 SyslogIdentifier= 来防止脚本的名称显示 Journalctl 输出。)通常不鼓励使用包装器脚本,但这通常是因为它们执行的操作可以通过 .service 轻松完成,但这里的情况并非 100%。
避免systemctl set-environment
,因为它是全局的 - 变量将可供全部服务从那时起开始,无论他们是否想要。