systemd服务环境变量缺失的根本原因是其不继承shell环境且不加载/etc/profile等配置文件;需在.service文件[Service]区块中用Environment=显式声明PATH、LD_LIBRARY_PATH等变量,并执行daemon-reload和restart生效。

Systemd 服务启动后环境变量缺失(比如 PATH、LD_LIBRARY_PATH 不生效),是常见但容易被误判的问题。根本原因是:systemd 启动的服务不继承 shell 的环境,也不自动加载 /etc/profile 或用户 shell 配置文件。
确认是否真缺环境变量
别猜,先验证:
- 手动运行服务命令(用 service 文件里
User=指定的用户):sudo -u www-data /usr/bin/myapp --version
看是否正常;再对比 systemd 启动后的实际环境: - 查进程真实环境:
cat /proc/$(pidof myapp)/environ | tr '\0' '\n' | grep -E '^(PATH|LD_LIBRARY_PATH)=' - 如果手动运行有、systemd 启动后没有,基本锁定为环境变量未注入。
检查 systemd 服务配置中是否正确定义了 Environment
打开服务文件(如 /etc/systemd/system/myapp.service),重点看 [Service] 区块:
- 必须用
Environment=显式声明,例如:Environment="PATH=/usr/local/bin:/usr/bin:/bin"Environment="LD_LIBRARY_PATH=/app/lib:/usr/local/lib" - 支持多行写法:
Environment="A=1"Environment="B=2" - 不能写成
EnvironmentFile=/etc/default/myapp却忘了创建该文件或设错权限(需 root 可读)。
排查 LD_LIBRARY_PATH 类动态库路径失效
即使 LD_LIBRARY_PATH 在 environ 里显示存在,程序仍可能报 libxxx.so: cannot open shared object file —— 这往往是因为 systemd 启动时绕过了它,直接依赖系统级动态链接器缓存。
- 检查
/etc/ld.so.conf.d/下是否已添加对应路径,例如:echo "/app/lib" | sudo tee /etc/ld.so.conf.d/myapp.conf - 立即更新缓存:
sudo ldconfig -v | grep myapp(确认路径已加载) - 这样所有进程(包括 systemd 服务)都能通过
ld.so找到库,不依赖环境变量。
避免踩坑的实操建议
- 改完服务文件后,一定执行:
sudo systemctl daemon-reload(重载配置)sudo systemctl restart myapp.service(重启服务) - 不要在
ExecStart中用source /etc/profile && ...—— systemd 不解析 shell 语法,会直接把整行当命令字面量执行,导致失败。 - 如果服务依赖大量环境变量,优先考虑用
EnvironmentFile=外部管理,但要确保文件存在、权限为644、所有变量格式为KEY=VALUE(无空格、无引号)。


















