在 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。支持使用 # 或 ; 开头写注释。
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:重载并重启
修改单元文件后必须重载守护进程配置,然后重启服务使变量生效。
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:检查服务日志
如果程序启动时会打印配置信息,查看日志确认读取到的值是否符合预期。
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