怎么在 systemd 服务中配置环境变量 EnvironmentFile

文章导读
在 systemd 服务中配置环境变量 EnvironmentFile,需在单元文件的 [Service] 段落添加 EnvironmentFile= 路径指向一个 KEY=VALUE 格式的文本文件。此方法适合将敏感配置与代码分离,风险在于文件权限错误或语法格式不对会导致服务启动失败。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

在 systemd 服务中配置环境变量 EnvironmentFile,需在单元文件的 [Service] 段落添加 EnvironmentFile= 路径指向一个 KEY=VALUE 格式的文本文件。此方法适合将敏感配置与代码分离,风险在于文件权限错误或语法格式不对会导致服务启动失败。

先说结论:EnvironmentFile 指令允许 systemd 在启动服务前加载外部文件中的环境变量,适用于管理数据库密码、API 密钥等敏感信息。

  • 适合:需要将配置与程序代码分离的场景,或不同环境使用不同变量值的场景。
  • 先准备:创建权限正确的环境变量文件,确保 systemd 用户可读。
  • 验收:修改单元文件后执行 daemon-reload,重启服务并检查进程环境变量。

命令速用版

以下命令展示创建环境变量文件、修改单元文件并重启服务的核心操作。

# 1. 创建环境变量文件
sudo tee /etc/myapp/env.conf >/dev/null <<EOF
DB_HOST=127.0.0.1
DB_PASS=secret_password
EOF

# 2. 设置文件权限(仅 root 可读)
sudo chmod 600 /etc/myapp/env.conf

# 3. 编辑 systemd 单元文件,在 [Service] 段添加
# EnvironmentFile=/etc/myapp/env.conf

# 4. 重载配置并重启服务
sudo systemctl daemon-reload
sudo systemctl restart myapp.service

为什么会这样

systemd 设计 EnvironmentFile 是为了实现配置与代码解耦,避免将敏感信息硬编码在单元文件中。

单元文件通常位于 /usr/lib/systemd/system/ 或 /etc/systemd/system/,可能被版本管理工具跟踪或对所有用户可读。使用独立的环境文件可以单独控制文件权限(如 chmod 600),限制只有 root 或特定用户能读取密码。此外,同一套单元文件可以通过加载不同的 EnvironmentFile 适配开发、测试和生产环境,无需修改单元文件本身。

分步处理

按顺序执行以下步骤完成配置,每步完成后检查状态再继续。

步骤 1:创建环境变量文件

在 /etc 目录下创建配置文件,格式为每行一个 KEY=VALUE。支持使用 # 或 ; 开头写注释。

怎么在 systemd 服务中配置环境变量 EnvironmentFile
sudo mkdir -p /etc/myapp
sudo nano /etc/myapp/env.conf

文件内容示例:

# 数据库配置
DB_HOST=192.168.1.10
DB_PORT=5432
# 敏感信息
API_KEY=xyz123456

步骤 2:设置文件权限

确保文件所有者为 root,权限设置为 600 或 640,防止普通用户读取敏感信息。

sudo chown root:root /etc/myapp/env.conf
sudo chmod 600 /etc/myapp/env.conf

步骤 3:修改 systemd 单元文件

编辑服务单元文件,在 [Service] 段落添加 EnvironmentFile 指令。若文件可能不存在但不想报错,可在路径前加负号 -。

[Service]
EnvironmentFile=/etc/myapp/env.conf
# 或者忽略文件缺失错误
# EnvironmentFile=-/etc/myapp/optional.conf
ExecStart=/usr/bin/myapp

步骤 4:重载并重启

修改单元文件后必须重载守护进程配置,然后重启服务使变量生效。

怎么在 systemd 服务中配置环境变量 EnvironmentFile
sudo systemctl daemon-reload
sudo systemctl restart myapp.service

怎么验证是否生效

通过 systemctl show 命令或查看进程文件系统确认环境变量已加载。

方法 1:使用 systemctl show

查看服务加载的环境变量列表,输出包含 Environment 字段。

systemctl show myapp.service | grep Environment

方法 2:查看进程 environ 文件

找到服务主进程 PID,读取 /proc/<pid>/environ 文件,null 字符分隔。

MAIN_PID=$(systemctl show myapp.service -p MainPID `--value`)
cat /proc/$MAIN_PID/environ | tr '\0' '\n' | grep DB_HOST

方法 3:检查服务日志

如果程序启动时会打印配置信息,查看日志确认读取到的值是否符合预期。

怎么在 systemd 服务中配置环境变量 EnvironmentFile
journalctl -u myapp.service -n 50

常见坑

配置 EnvironmentFile 时容易因格式或权限问题导致服务启动失败。

  • 空格问题:KEY 和 VALUE 之间不能有空格,即必须是 KEY=VALUE,写成 KEY = VALUE 会导致变量名包含空格。
  • 引号处理:值两边的引号会被保留,除非使用特定语法。若值包含空格,建议用双引号包裹,如 MSG="Hello World"。
  • 文件缺失:默认情况下文件不存在会导致服务启动失败。若文件可选,需在路径前加 -,如 EnvironmentFile=-/etc/optional.conf。
  • 变量扩展:EnvironmentFile 中的变量默认不进行 shell 扩展。若需要使用 $HOME 等变量,需在单元文件中使用 Environment= 指令配合。
  • 权限不足:systemd 系统实例以 root 运行,但若服务配置了 User= 指定用户,需确保该用户有权限读取环境变量文件。

常见问题

EnvironmentFile 和 Environment 指令有什么区别?

Environment 直接在单元文件中写变量,EnvironmentFile 从外部文件读取。

Environment 适合少量非敏感变量,内容直接可见于单元文件。EnvironmentFile 适合大量配置或敏感信息,便于权限管理和环境切换。两者可以同时使用,EnvironmentFile 加载的变量可以被 Environment 覆盖。

可以在一个服务中配置多个 EnvironmentFile 吗?

可以,systemd 支持多次使用 EnvironmentFile 指令加载多个文件。

后续文件中的同名变量会覆盖前面文件中的值。例如先加载 /etc/default/app,再加载 /etc/app/override.conf,后者优先级更高。

修改环境变量文件后需要 reload 吗?

仅修改环境变量文件内容不需要 daemon-reload,但需要重启服务。

若修改了单元文件中的 EnvironmentFile 路径配置,则必须执行 systemctl daemon-reload。若只改了文件里的值,直接 systemctl restart 服务即可生效。

参考来源

  • freedesktop.org, systemd.exec — Execution environment configuration, https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html