port-process

Installation
SKILL.md

Port and Process Management

Find What's Using a Port

# macOS and Linux
lsof -i :3000

# Linux only (faster)
ss -tlnp | grep :3000

# Older Linux systems
netstat -tlnp | grep :3000

# Show all listening ports
lsof -i -P -n | grep LISTEN
ss -tlnp

lsof -i :PORT works on both macOS and Linux and is the most reliable first choice. On Linux, ss is faster and preferred over the deprecated netstat.

Kill a Process

# By PID
kill 12345          # SIGTERM (graceful)
kill -9 12345       # SIGKILL (forced, last resort)

# By port — kill whatever is on port 3000
lsof -ti :3000 | xargs kill
lsof -ti :3000 | xargs kill -9   # forced

# By name
pkill node
pkill -f "next dev"
killall node        # macOS/Linux, kills all matching by exact name

The -t flag in lsof -ti outputs only PIDs, making it pipeable to kill.

macOS vs Linux Differences

Task macOS Linux
Port lookup lsof -i :PORT lsof -i :PORT or ss -tlnp
Kill by port lsof -ti :PORT | xargs kill fuser -k PORT/tcp
Process tree pstree PID (install via brew) pstree -p PID or ps --forest
Network stats netstat -an (no -p flag) ss -tlnp or netstat -tlnp
File descriptors lsof -p PID ls /proc/PID/fd or lsof -p PID

On macOS, ss and fuser are not available. Stick with lsof.

"Address Already in Use" Diagnostic Flow

When you hit EADDRINUSE or "address already in use":

# 1. Find what owns the port
lsof -i :3000

# 2. Check if it's your own stale process
lsof -i :3000 -sTCP:LISTEN

# 3. Get details on the PID
ps -p <PID> -o pid,ppid,user,command

# 4. Graceful kill first
kill <PID>

# 5. Verify it released
lsof -i :3000

# 6. If still stuck, force kill
kill -9 <PID>

# 7. If port is in TIME_WAIT (Linux), you can reuse it
# Add SO_REUSEADDR in code, or wait ~60 seconds
ss -tlnp | grep :3000

If the port is held by a process with PPID 1, it is orphaned. Kill it directly.

Find Processes by Name

# Search running processes
ps aux | grep node
ps aux | grep -v grep | grep node   # exclude the grep itself

# Better alternatives
pgrep -la node        # list PIDs and command lines
pgrep -f "next dev"   # match full command string
pidof node            # Linux only, returns PIDs

# Detailed info for a known PID
ps -p 12345 -o pid,ppid,user,%cpu,%mem,etime,command

Process Tree

# Linux
pstree -p 12345       # show tree rooted at PID
ps -ejH               # tree view of all processes
ps --forest -eo pid,ppid,cmd

# macOS (install pstree via: brew install pstree)
pstree 12345

# Find parent of a process
ps -o ppid= -p 12345

Useful for finding which shell or supervisor spawned a runaway process.

Background and Foreground

# Run in background
node server.js &

# List background jobs in current shell
jobs

# Bring job #1 to foreground
fg %1

# Send foreground job to background
# Press Ctrl-Z first (suspends it), then:
bg %1

# Detach from terminal (survives logout)
nohup node server.js > output.log 2>&1 &

# Disown an already-running background job
node server.js &
disown %1

# disown makes the shell forget about the job so it won't get SIGHUP on exit

Resource Usage

# Interactive process monitor
top                   # built-in everywhere
htop                  # better UI (install separately)

# One-shot: top processes by CPU
ps aux --sort=-%cpu | head -20        # Linux
ps aux -r | head -20                  # macOS (sorted by CPU)

# One-shot: top processes by memory
ps aux --sort=-%mem | head -20        # Linux
ps aux -m | head -20                  # macOS (sorted by memory)

# Memory summary
free -h               # Linux only
vm_stat               # macOS (pages, divide by 4096 for bytes)

Disk Usage

# Filesystem overview
df -h

# Size of a directory
du -sh /path/to/dir

# Find large directories (top 10)
du -h /path | sort -rh | head -10

# Interactive disk usage explorer
ncdu /path            # install separately, very useful

# Find files over 100MB
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null

# Docker disk usage (common space hog)
docker system df
docker system prune -a   # reclaim space, removes unused images/containers

File Descriptors

# Check current limits
ulimit -n             # soft limit for open files
ulimit -Hn            # hard limit

# Raise soft limit for current session
ulimit -n 65536

# List open files for a process
lsof -p 12345
lsof -p 12345 | wc -l   # count them

# Linux: inspect directly
ls /proc/12345/fd | wc -l

# Find processes with many open files (Linux)
for pid in /proc/[0-9]*; do
  echo "$(ls $pid/fd 2>/dev/null | wc -l) $pid"
done | sort -rn | head -10

If a process hits the file descriptor limit, it logs errors like "too many open files." Raise ulimit -n or fix the file/socket leak.

Signals

Signal Number Behavior When to use
SIGTERM 15 Graceful shutdown, process can catch and clean up Default. Always try first.
SIGINT 2 Same as Ctrl-C Interactive stop
SIGHUP 1 Hangup. Some daemons reload config on SIGHUP. Reload config (nginx, Apache)
SIGKILL 9 Immediate termination, cannot be caught Process ignores SIGTERM
SIGSTOP 19 Pause process (like Ctrl-Z) Temporarily freeze a process
SIGCONT 18 Resume stopped process Unpause after SIGSTOP

Always send SIGTERM first. Give it a few seconds. Only use SIGKILL (kill -9) when the process refuses to exit. SIGKILL skips all cleanup -- temp files, lock files, and sockets will be left behind.

kill PID              # SIGTERM
kill -HUP PID         # SIGHUP (reload)
kill -9 PID           # SIGKILL (last resort)

Common Scenarios

Dev server won't start (port taken)

lsof -ti :3000 | xargs kill
# then restart your server

Orphaned Node.js process eating CPU

pgrep -la node
# identify the stale one by its command line
kill <PID>

Multiple stale dev servers

# Kill all node processes (careful in production)
pkill -f "next dev"
pkill -f "vite"
pkill -f "react-scripts"

Out of disk space

df -h                           # confirm which volume is full
du -h /home --max-depth=2 | sort -rh | head -20   # find biggest dirs
# Common culprits:
docker system prune -a          # unused Docker data
rm -rf node_modules/.cache      # build caches
npm cache clean --force         # npm cache

Zombie processes

# Find zombies
ps aux | awk '$8=="Z"'

# Zombies can't be killed directly -- kill their parent instead
ps -o ppid= -p <ZOMBIE_PID>
kill <PARENT_PID>

A zombie is a process that finished but whose parent hasn't read its exit status. Killing the parent lets init/systemd reap it.

Related skills

More from 1mangesh1/dev-skills-collection

Installs
1
GitHub Stars
3
First Seen
Apr 14, 2026