systemd 环境变量 PATH
在 systemd 服务脚本中扩展 PATH 环境变量,可以通过 Environment= 或 EnvironmentFile= 指令在 [Service] 节设置,使用 PATH=/new/path:$PATH 语法追加新路径,或在单独的文件中定义后再引用。
在 systemd 服务单元文件(如 /etc/systemd/system/my-service.service)的 [Service] 段落中添加 Environment 指令:
[Unit]
Description=My Custom Service
[Service]
Type=simple
ExecStart=/usr/local/bin/my_app
# 扩展 PATH,将 /opt/mytools/bin 添加到现有 PATH 的最前面
Environment="PATH=/opt/mytools/bin:$PATH"
# 或者添加在末尾
# Environment="PATH=$PATH:/opt/mytools/bin"
User=myuser
[Install]
WantedBy=multi-user.target
创建一个包含环境变量的文件,例如 /etc/sysconfig/my-app-env 或 /etc/default/my-app-env:
# /etc/sysconfig/my-app-env
MY_APP_HOME=/usr/local/myapp
# 追加新的路径
PATH=/usr/local/myapp/bin:$PATH
# 或者用更标准的方式覆盖并追加
# PATH=/opt/new_tools/bin:$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
在 systemd 服务单元文件中使用 EnvironmentFile 指令引用:
[Service]
Type=simple
ExecStart=/usr/local/bin/my_app
EnvironmentFile=/etc/sysconfig/my-app-env
User=myuser
$PATH 引用了系统默认的 PATH 变量值。
路径顺序决定优先级,位于 $PATH 前面的路径会被优先搜索。
修改后需要执行 sudo systemctl daemon-reload 和 sudo systemctl restart my-service 使更改生效。
# 环境变量
Environment="PATH=/usr/local/jdk/21.0.9/bin:$PATH"
Environment="JENKINS_HOME=/data/jenkins/data"
# 工作目录
WorkingDirectory=/data/jenkins/war
# 启动命令
ExecStart=java -jar jenkins.war --httpPort=8910 --prefix=/jenkins
Failed at step EXEC spawning java: No such file or directory
通常 不是 PATH 配置的问题,而是 systemd 找不到 java 可执行文件。
原因和解决方法如下:
你写的 ExecStart 是:
ExecStart=java -jar jenkins.war --httpPort=8910 --prefix=/jenkins
systemd 不会自动加载 shell 环境变量,包括 $PATH。
虽然你用:
Environment="PATH=/usr/local/jdk/21.0.9/bin:$PATH"
但 $PATH 在 systemd 环境中 不被扩展,$PATH 会被当作字面值。
所以 systemd 执行 java 时找不到可执行文件,报 No such file or directory。
ExecStart=/usr/local/jdk/21.0.9/bin/java -jar jenkins.war --httpPort=8910 --prefix=/jenkins
这是最可靠的方法,也是生产环境推荐做法。
Environment="PATH=/usr/local/jdk/21.0.9/bin:/usr/bin:/bin"
ExecStart=java -jar jenkins.war --httpPort=8910 --prefix=/jenkins
注意:systemd 不会展开 $PATH,必须写完整路径。
ExecStart=/bin/sh -c 'java -jar jenkins.war --httpPort=8910 --prefix=/jenkins'
systemd 会调用 shell 去解析 $PATH,可行但增加一层 shell,调试不方便。
[Unit]
Description=Jenkins CI Server
After=network.target
[Service]
Type=simple
User=jenkins
Group=jenkins
Environment="JENKINS_HOME=/data/jenkins/data"
WorkingDirectory=/data/jenkins/war
ExecStart=/usr/local/jdk/21.0.9/bin/java -jar jenkins.war --httpPort=8910 --prefix=/jenkins
Restart=always
RestartSec=5s
StandardOutput=journal
StandardError=journal
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
/data/jenkins/war/jenkins.war 必须存在并有 jenkins 用户访问权限。
日志查看:
journalctl -u jenkins -f
修改 systemd 文件后别忘了:
systemctl daemon-reload
systemctl restart jenkins
- systemd 不会展开 $PATH
- 生产环境推荐 ExecStart 用 java 全路径
- $PATH 可以设置,但不要写 $PATH,写完整路径即可