341 words, 2 min read

When you run multiple instances of the same Laravel Horizon worker (or any supervisord-managed process) across different deployment directories, you'll quickly notice that supervisord assigns generic auto-generated names like daemon-282661:daemon-282661_00. There's no obvious way to tell which daemon belongs to which application directory — until you know the trick.

Finding the working directory of a process

On Linux, every running process exposes its current working directory as a symlink under /proc:

readlink /proc/<pid>/cwd

To check all your Horizon workers at once, grab their PIDs from supervisorctl status and loop over them:

for pid in 91286 91287 91288 91290; do
echo "$pid: $(readlink /proc/$pid/cwd)"
done

Restarting daemons for a specific directory

Once you can map PIDs to directories, it's straightforward to build a script that restarts only the daemons running from a given path:

#!/bin/bash
TARGET_DIR="${1:?Usage: $0 <working-directory>}"
TARGET_DIR=$(realpath "$TARGET_DIR")
supervisorctl status | while read -r line; do
echo "$line" | grep -q "RUNNING" || continue
name=$(echo "$line" | awk '{print $1}')
pid=$(echo "$line" | grep -oP 'pid \K[0-9]+')
[[ -z "$pid" ]] && continue
cwd=$(readlink "/proc/$pid/cwd" 2>/dev/null)
if [[ "$cwd" == "$TARGET_DIR"* ]]; then
echo "Restarting $name (pid $pid, dir $cwd)"
supervisorctl restart "$name"
fi
done

How it works

  1. supervisorctl status lists all daemons with their current PIDs.
  2. Non-RUNNING daemons are skipped (they have no PID to look up).
  3. /proc/<pid>/cwd resolves the actual working directory for each process.
  4. Any daemon whose working directory matches the target path (or is a subpath of the target path) gets restarted.

Usage

chmod +x restart-daemons.sh
./restart-daemons.sh /home/forge/my-app/current

This is especially useful on servers running multiple deployments of the same application — for example, a staging environment with both a current and a previous release still running workers.