| name | process-mgmt |
| description | MANDATORY skill for spawning and killing processes |
Process Management Skill - MANDATORY
Safe process lifecycle management in terminal environments where pkill and pgrep -f are unsafe due to subprocess self-matching.
CRITICAL: This skill is MANDATORY for all processes involving starting, stopping, or managing background services (servers, daemons, test runners, etc.). Violations cause infinite loops and hung shells.
WHY THIS EXISTS
The bash tool runs commands via bash -c "...". When you run pkill -f pattern, the -f flag causes pkill to match against the full command line including itself (bash -c "... pkill -f ..."), creating an infinite kill loop that hangs the shell indefinitely.
PROHIBITED Commands
These commands MUST NEVER be used:
pkill <pattern>
pkill -f <pattern>
pgrep -f <pattern>
pkillall
killall
Safe Alternatives
Method 1: Justfile Recipes (PREFERRED)
Most projects provide justfile recipes for daemon management:
just site-stop
just site-serve
just daemon-stop
just daemon-start
just daemon-restart
just daemon-status
Always prefer project-provided recipes over manual process management.
Method 2: PID Files
Store PIDs at startup, read them for cleanup:
myserver &
echo $! > /tmp/myserver.pid
kill $(cat /tmp/myserver.pid) 2>/dev/null || true
rm -f /tmp/myserver.pid
Method 3: Process Group Kill
For related processes started from same command:
( myserver && another-server ) &
echo $! > /tmp/servers.gid
kill -- -$(cat /tmp/servers.gid) 2>/dev/null || true
Method 4: PID from Status/Info Commands
Many servers expose their PIDs:
PID=$(grep -oP 'PID: \K\d+' <(myserver --status))
kill "$PID"
PID=$(jq '.pid' /path/to/state.json)
kill "$PID"
Method 5: Signal-based Graceful Shutdown
Prefer SIGTERM for graceful shutdown, with timeout fallback:
if [ -f /tmp/server.pid ]; then
PID=$(cat /tmp/server.pid)
kill "$PID" 2>/dev/null || true
sleep 2
kill -0 "$PID" 2>/dev/null && kill -9 "$PID" 2>/dev/null || true
rm -f /tmp/server.pid
fi
Method 6: Named Socket/Port Check
For servers that bind ports:
ss -tlnp | grep -q ':9999' && echo "running" || echo "stopped"
Common Patterns
Start-if-not-running guard:
start_server() {
local pid_file="/tmp/myserver.pid"
if [ -f "$pid_file" ]; then
local existing_pid=$(cat "$pid_file")
kill -0 "$existing_pid" 2>/dev/null && {
echo "Server already running (PID: $existing_pid)"
return 0
}
fi
myserver &
echo $! > "$pid_file"
}
Stop-if-running guard:
stop_server() {
local pid_file="/tmp/myserver.pid"
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
kill "$pid" 2>/dev/null || true
rm -f "$pid_file"
fi
}
Process State Inspection (without pgrep -f)
kill -0 $PID 2>/dev/null && echo "alive" || echo "dead"
ps aux | grep '[s]erver'
lsof -i :9999 2>/dev/null
ss -tlnp sport = :9999
pstree -p $$ | head
Troubleshooting Stuck Processes
if [ -f /tmp/server.pid ]; then
kill -0 $(cat /tmp/server.pid) 2>/dev/null || rm -f /tmp/server.pid
fi
ss -tlnp sport = :9999
LSPID=$(lsof -ti :9999 2>/dev/null)
kill $LSPID 2>/dev/null || true
ps aux | grep '[Z]'
When to Use Each Method
| Situation | Preferred Method |
|---|
| Project provides justfile recipes | Method 1 (just recipes) |
| Starting server in current session | Method 2 (PID file) |
| Multiple related servers | Method 3 (process group) |
| Server exposes status/PID info | Method 4 (status commands) |
| Need graceful shutdown | Method 5 (signal-based) |
| Checking if server is up | Method 6 (port check) |
Key Takeaways
- NEVER use
pkill, pgrep -f, or killall
- ALWAYS prefer project-provided justfile recipes
- Store PIDs in files when starting processes
- Use
kill -0 PID to check if process is alive
- Kill by explicit PID:
kill $PID
- For servers: check ports with
ss or lsof
Last Updated: 2026-05-12