在 Systemd 上使用 ExecStartPre 创建操作系统环境变量

在 Systemd 上使用 ExecStartPre 创建操作系统环境变量

我有以下单元文件:

[Unit]
Description=Panel for Systemd Services
After=network.target

[Service]
User=pysd
Group=pysd
PermissionsStartOnly=true
WorkingDirectory=/opt/pysd
ExecStartPre=/bin/mkdir /run/pysd
ExecStartPre=/bin/chown -R pysd:pysd /run/pysd
ExecStart=/usr/local/bin/gunicorn app:app -b 127.0.0.1:8100 --pid /run/pysd/pysd.pid --workers=2
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
ExecStopPost=/bin/rm -rf /run/pysd
PIDFile=/run/pysd/pysd.pid
PrivateTmp=true

[Install]
WantedBy=multi-user.target
Alias=pysd.service

我想创建一个环境变量,ExecStartPre然后将该变量合并到ExecStart.

更具体地说,我想GUNICORN_SERVER在运行之前创建一个环境变量ExecStart,然后将此环境变量用于选项-bat ExecStart

我尝试了类似的方法ExecStartPre=/bin/bash -c 'export GUNICORN_SERVER=127.0.0.1:8100',但没有创建环境变量。

我如何实现这个场景?

答案1

您不能用于直接设置其他命令ExecStartPre的环境- 这些都是单独的进程。 (间接地,通过保存到文件并读取它或其他东西,当然。)ExecStartPreExecStart

Systemd 有两种设置环境的方法:Environment=EnvironmentFile=。两者都有例子man 5 systemd.exec。这些会影响该服务启动的所有进程,包括ExecStartPre.如果这些变量不必动态设置,那么这些是一个不错的选择:

Environment=GUNICORN_SERVER=127.0.0.1:8080

但是,如果您需要动态设置变量,则联机帮助页会说明以下内容EnvironmentFile

The files listed with this directive will be read shortly before the process is
executed (more specifically, after all processes from a previous unit state
terminated. This means you can generate these files in one unit state, and read it
with this option in the next).

因此,一种选择是将其写入 中的文件ExecStartPre,并让 systemd 读取该文件作为 的一部分EnvironmentFile

EnvironmentFile=/some/env/file
ExecStartPre=/bin/bash -c 'echo foo=bar > /some/env/file'
ExecStart=/some/command  # sees bar as value of $foo

另一种选择是在以下位置使用 shell ExecStart

ExecStart=/bin/sh -c 'export GUNICORN_SERVER=127.0.0.1:8080; exec /usr/local/bin/gunicorn ...'

答案2

事实上,最好的方法是使用--envGunicorn,它在操作系统上创建一个环境变量,您可以读取该变量并将数据合并到您的 Python 应用程序中:

在您的单位文件上:

ExecStart=/usr/local/bin/gunicorn app:app -b 127.0.0.1:8100 --env GUNICORN_SERVER="127.0.0.1:8100" --pid /run/pysd/pysd.pid --workers=2

在您的应用程序上(例如 Flask):

import os
from flask import Flask

app = Flask(__name__)

gs = os.getenv('GUNICORN_SERVER')
if gs:
    app.config["SERVER_NAME"] = gs                                              
else:
    app.config["SERVER_NAME"] = "127.0.0.1:8100"

感谢您的评论,JdeBP。这文档确实有很多信息。

相关内容