如何在 systemd 单元文件中指定动态“环境”变量?

如何在 systemd 单元文件中指定动态“环境”变量?

$(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,因为它是全局的 - 变量将可供全部服务从那时起开始,无论他们是否想要。

相关内容