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.pid
file (/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 3
if 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.pid
files. - 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.
Leave a Reply