How to Properly Escape Spaces in systemd Unit File Paths: A Complete Guide


2 views

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