workingdirectory不可省略,因systemd默认工作目录为/或用户家目录,导致相对路径失效;必须设为存在的绝对路径(如/opt/myapp),否则启动失败或i/o错误。

必须显式设置 WorkingDirectory,否则 Java 进程默认在 root 或 systemd 启动用户的家目录下运行,相对路径会全部失效。
WorkingDirectory 为什么不能省略
Java 应用(尤其是 Spring Boot)常依赖相对路径加载配置文件(application.yml)、静态资源、日志输出目录或临时文件。systemd 默认不继承 shell 的当前路径,且启动时工作目录是不确定的(通常是 / 或用户家目录)。不设 WorkingDirectory 就等于让 java -jar myapp.jar 在根目录下执行 —— 所有 ./config/、logs/、data/ 都会找错地方。
- 常见错误现象:
java.io.FileNotFoundException: ./config/application.yml,但文件明明就在 jar 包同级目录 - Spring Boot 的
--spring.config.location=file:./config/会完全失效 - Logback 的
<file>logs/app.log</file>会尝试写入/logs/app.log,权限拒绝或磁盘满
WorkingDirectory 必须是绝对路径且目录存在
systemd 严格校验该路径:不存在 → 启动直接失败,报 Failed at step CHDIR spawning ...: No such file or directory;权限不足 → 报 Permission denied。它不支持 ~、../ 或环境变量展开(除非用 %h 等内置替换符)。
- 正确写法:
WorkingDirectory=/opt/myapp(确保该目录已mkdir -p /opt/myapp创建) - 错误写法:
WorkingDirectory=~/myapp、WorkingDirectory=./myapp、WorkingDirectory=$HOME/myapp - 若需动态指向用户家目录,可用
WorkingDirectory=/home/%u/myapp(配合User=appuser) - 目录权限必须允许服务用户读+执行(
r-x),否则cd失败
WorkingDirectory 和 ExecStart 路径的关系
WorkingDirectory 只影响进程启动后的当前目录,不影响 ExecStart 中命令本身的路径解析。Java 命令和 JAR 包路径仍需写绝对路径 —— 这是两个独立维度。
-
WorkingDirectory=/opt/myapp+ExecStart=/usr/bin/java -jar /opt/myapp/app.jar✅ -
WorkingDirectory=/opt/myapp+ExecStart=/usr/bin/java -jar app.jar❌(systemd 不在 WorkingDirectory 下查找 jar) - 如果 jar 包里内嵌了配置,且你用
--spring.config.location=file:/opt/myapp/config/,那WorkingDirectory对它没影响;但如果用file:./config/,就必须靠WorkingDirectory定位
验证 WorkingDirectory 是否生效
别只看服务是否“启动成功”,要确认进程实际工作目录是否如预期。最直接的方法是查 systemd 记录的启动上下文:
- 运行
systemctl show --property=WorkingDirectory myapp.service,看输出是否为你设的绝对路径 - 查进程当前目录:
sudo ls -l /proc/$(systemctl show --property=MainPID myapp.service | cut -d= -f2)/cwd,应指向你设的目录 - 临时加一行调试:在
ExecStart前加ExecStartPre=/bin/sh -c 'pwd > /tmp/myapp-pwd.log',启动后看日志内容
最容易被忽略的是:WorkingDirectory 设置后,所有基于相对路径的 I/O 行为都以此为准,包括 JVM 自身的日志、JNA 加载的 native 库路径、甚至某些 JNI 调用 —— 它不是“仅对 Spring 有效”的配置项。











