On Ubuntu systems, /var/run
typically has these permissions:
drwxr-xr-x 9 root root 4096 Mar 15 09:00 /var/run
This means only root can create files directly in this directory. When your daemon (running as a non-root user) attempts to create a PID file there, you'll encounter:
touch: cannot touch /var/run/test.pid': Permission denied
Here are several solutions, ordered by recommended practice:
1. Use /run/user or Systemd's RuntimeDirectory
Modern systems provide better alternatives:
# For systemd services
RuntimeDirectory=myprogram
RuntimeDirectoryMode=0755
This creates /run/myprogram
automatically.
2. Directory Ownership During Installation
If you're creating a package, set this in postinst:
#!/bin/sh
set -e
mkdir -p /var/run/myprogram
chown myprogram-user:myprogram-group /var/run/myprogram
chmod 755 /var/run/myprogram
3. Temporary Directory Approach
For non-package installations:
PID_DIR="/var/run/myprogram"
if [ ! -d "$PID_DIR" ]; then
install -d -o myprogram-user -g myprogram-group -m 0755 "$PID_DIR"
fi
Here's how to properly implement this:
#!/bin/sh
PIDFILE="/var/run/myprogram/myprogram.pid"
DAEMON_USER="myprogram-user"
# Ensure PID directory exists
if [ ! -d "$(dirname "$PIDFILE")" ]; then
install -d -o "$DAEMON_USER" -g "$DAEMON_USER" -m 0755 "$(dirname "$PIDFILE")"
fi
start-stop-daemon --start --chuid "$DAEMON_USER" \
--pidfile "$PIDFILE" --make-pidfile \
--exec /usr/bin/myprogram -- $OPTIONS
For systemd systems, create /etc/tmpfiles.d/myprogram.conf
:
d /var/run/myprogram 0755 myprogram-user myprogram-group -
This directory will be created at boot with correct permissions.
When implementing PID file handling:
- Never run your daemon as root just to write PID files
- Avoid world-writable directories
- Consider using abstract namespace sockets for modern applications
- Implement proper file locking when writing PID files
If issues persist:
# Check directory permissions
ls -ld /var/run/myprogram
# Verify user can write
sudo -u myprogram-user touch /var/run/myprogram/test.tmp
# Check for SELinux/AppArmor
dmesg | grep avc
aa-status
On modern Ubuntu systems (using systemd), /var/run
is typically a symlink to /run
, which has the following permissions:
drwxr-xr-x 9 root root 180 Apr 10 15:30 /run
This directory is specifically designed for runtime variable data and traditionally requires root privileges for writing. For daemons that need to write PID files here, we have several approaches.
For systemd services, the recommended approach is to use PrivateTmp
:
[Service]
User=my-program-user
PrivateTmp=yes
RuntimeDirectory=my-program
PIDFile=/run/my-program/pid
This automatically creates a subdirectory under /run
with proper permissions.
If you're not using systemd, you can create a dedicated directory during package installation:
# In postinst script of your deb package
install -d -o my-program-user -g my-program-group /var/run/my-program
chmod 755 /var/run/my-program
When using start-stop-daemon
with a non-root user, specify both the --pidfile
and --make-pidfile
options:
start-stop-daemon --start --chuid my-program-user \
--pidfile /var/run/my-program.pid --make-pidfile \
--exec /usr/sbin/my-program
For system persistence, create a configuration file in /etc/tmpfiles.d/my-program.conf
:
d /run/my-program 0755 my-program-user my-program-group -
This ensures the directory is created with correct permissions at boot.
If you still encounter problems, check:
- Effective permissions with
namei -l /var/run/my-program.pid
- Process capabilities with
getcap /usr/sbin/my-program
- SELinux/AppArmor denials in system logs