Quick Fix: Nginx PID Errors on macOS (Apple Silicon + Homebrew)
If you run Nginx on an Apple Silicon Mac using Homebrew, you may see errors after a reboot caused by a stale /opt/homebrew/var/run/nginx.pid. I wrote a small ZSH script to remove the stale PID, restart Nginx, and confirm it’s actually serving traffic.

If you’re running macOS on an Apple Silicon Mac (M1, M2, M3) with Nginx installed via Homebrew, you might have seen this after a reboot:
nginx: [error] invalid PID number "" in "/opt/homebrew/var/run/nginx.pid"This happens because Nginx keeps a PID file for its running process. Sometimes, after a reboot, that file is left behind, and Nginx refuses to start or reload.
I hit this enough times that I scripted a fix.
This script is tuned for Nginx installed via Homebrew on Apple Silicon. If you installed Nginx differently (for example, compiled from source or using a different path), you’ll need to modify the script — especially the path to the nginx.pid file.
Script Commands
nginxkill– Removes the stalenginx.pidfile (/opt/homebrew/var/run/nginx.pid).nginxreload– Reloads Nginx configuration and removes stale PID files if needed, then checks if Nginx is listening on port 80.nginxrestart🔥 – Stops and restarts Nginx, removes stale PID files if needed, then checks if Nginx is listening on port 80.spinner_wait– For fun, it displays a simple spinner while waiting (used insidenginxrestart). You can replace this with a simplesleep 3if you like. Nginx needs about 3 seconds to await the restart.
How to Use
Add these functions to your ~/.zshrc, reload your shell, then run nginxrestart whenever Nginx fails to start after a reboot.
# nginx
function nginxkill() {
sudo rm /opt/homebrew/var/run/nginx.pid
}
function nginxreload() {
echo "Reloading Nginx"
output=$(sudo nginx -s reload 2>&1)
echo "$output"
local GREEN="\033[0;32m"
local NC="\033[0m" # No Color
# More robust regex match (handles spacing and newlines)
if [[ "$output" =~ nginx\.pid && "$output" =~ error ]]; then
echo "PID file error detected. Removing stale nginx.pid..."
nginxkill
spinner_wait 3 # Wait 3 seconds for Nginx to fully start
fi
# --- Check if Nginx is actually serving traffic on port 80 ---
if sudo lsof -nP -iTCP:80 -sTCP:LISTEN | grep -q nginx; then
# Replace spinner with "Done!" in green
echo "Nginx is online and listening on port 80"
echo "${GREEN}PID error fixed!${NC}"
else
echo "Nginx failed to start or is not bound to port 80 (check logs)"
echo "Try running 'nginxkill' and then restarting Nginx again."
fi
}
function nginxrestart() {
echo "Restarting Nginx"
# Stop and start separately, capturing all output
stop_output=$(sudo nginx -s stop 2>&1)
start_output=$(sudo nginx 2>&1)
output="$stop_output"$'\n'"$start_output"
local GREEN="\033[0;32m"
local NC="\033[0m" # No Color
echo "$output"
# Use =~ regex match (handles variable spacing and order)
if [[ "$output" =~ nginx\.pid && "$output" =~ error ]]; then
echo "PID file error detected. Removing stale nginx.pid..."
nginxkill
spinner_wait 3 # Wait 3 seconds for Nginx to fully start
fi
# --- Check if Nginx is actually serving traffic on port 80 ---
if sudo lsof -nP -iTCP:80 -sTCP:LISTEN | grep -q nginx; then
echo "Nginx is online and listening on port 80"
echo "${GREEN}PID error fixed!${NC}"
else
echo "Nginx failed to start or is not bound to port 80 (check logs)"
echo "Try running 'nginxkill' and then restarting Nginx again."
fi
}
# spin for ~3 seconds
# spinner_wait 3 "Optional message"
spinner_wait() {
local duration=$1
local message=${2:-"Waiting... "}
local end=$((SECONDS + duration))
local chars=( "/" "-" "\\" "|" )
local i=0
local GREEN="\033[0;32m"
local NC="\033[0m" # No Color
# Print message and leave a space for spinner
echo -n "$message "
while (( SECONDS < end )); do
# \r returns to start of line, then reprint message and spinner
echo -ne "\r$message ${chars[i]}"
sleep 0.2
(( i = (i + 1) % ${#chars[@]} ))
done
# Replace spinner with "Done!" in green
echo -e "\r$message ${GREEN}Done!${NC}"
}Why This Helps
- Automatically removes stale
nginx.pidfiles. - Confirms Nginx is actually listening on port 80.
- Makes reboot issues on macOS less annoying.
Put this in your ~/.zshrc and you’re set, and do not forget to reload your ZSH/bash source.