When dealing with paths containing spaces in systemd unit files, many developers encounter unexpected behavior despite following the documentation. The key issue lies in understanding how systemd interprets escape sequences at different processing stages.
The \\x20
escape sequence works for command-line arguments in ExecStart
, but fails for directory paths in WorkingDirectory
. Systemd processes these configurations differently:
# This works for ExecStart but not WorkingDirectory
WorkingDirectory=/path/with\\x20spaces/ # Won't work
ExecStart=/path/with\\x20spaces/script.sh # Works
Here are three reliable methods to handle spaces in systemd paths:
1. Quoting the Entire Path
The most straightforward solution is to wrap the path in quotes:
[Service]
WorkingDirectory="/home/cobra/my service/"
ExecStart="/home/cobra/my service/start.sh"
2. Using the Octal Escape Sequence
For more complex paths, octal escaping might be preferable:
[Service]
WorkingDirectory=/home/cobra/my\040service/
ExecStart=/home/cobra/my\040service/start.sh
3. Symbolic Links as Workaround
When neither method works due to specific constraints, create a symlink:
ln -s "/home/cobra/my service" /home/cobra/myservice
Then reference it in your unit file:
[Service]
WorkingDirectory=/home/cobra/myservice/
ExecStart=/home/cobra/myservice/start.sh
- Always test with
systemd-analyze verify yourservice.service
- Check paths with
systemd-path
for proper expansion - Remember that
WorkingDirectory
must exist before service start
Here's a complete working example for a path containing multiple spaces:
[Unit]
Description=Multi-space Path Example
[Service]
Type=simple
WorkingDirectory="/opt/My Project Data/Log Processor/"
ExecStart="/opt/My Project Data/Log Processor/run.sh"
Restart=on-failure
User=appuser
[Install]
WantedBy=multi-user.target
The key takeaway is that while systemd's escaping rules can be tricky, quoting paths consistently provides the most reliable solution across different systemd versions.
When dealing with paths containing spaces in systemd unit files, developers often encounter the Failed at step CHDIR
error despite seemingly correct escaping. The root cause lies in how systemd interprets escaped sequences versus how the shell handles them.
The systemd documentation mentions using \x20
for spaces, but this only applies to specific contexts. For WorkingDirectory
and ExecStart
directives, we need different approaches:
# This WON'T work as expected:
WorkingDirectory=/home/cobra/my\x20service/
ExecStart=/home/cobra/my\x20service/start.sh
Method 1: Quoted Paths
The most reliable approach is to wrap the entire path in quotes:
[Service]
WorkingDirectory="/home/cobra/my service/"
ExecStart="/home/cobra/my service/start.sh"
Method 2: Full Octal Encoding
For complex paths, you can use octal encoding for each space:
[Service]
WorkingDirectory=/home/cobra/my\040service/
ExecStart=/home/cobra/my\040service/start.sh
After making changes, always verify with:
systemctl daemon-reload
systemctl start yourservice
journalctl -xe -u yourservice
For paths with multiple spaces, combine quoting with escaping:
[Service]
WorkingDirectory="/home/user/path\040with\040multiple\040spaces/"
ExecStart="/usr/bin/bash -c 'cd \"/home/user/path with multiple spaces/\" && ./script.sh'"
- Never mix quoting styles in the same directive
- Test with
systemd-analyze verify
before deployment - Consider path length limitations (systemd has a 108-character limit for AF_UNIX paths)
When all else fails, create a symlink without spaces:
ln -s "/home/cobra/my service/" /home/cobra/myservice
Then reference it in your unit file:
[Service]
WorkingDirectory=/home/cobra/myservice
ExecStart=/home/cobra/myservice/start.sh