Skip to content
Latchkey

nc -z (Port Check): Usage, Options & Common CI Errors

nc -z probes a TCP port without sending data - the standard CI readiness check.

Waiting for a service's port before running tests is the single most common networking task in CI, and nc -z -w is the idiom for it. The catch: netcat has incompatible variants, and -z behaves differently across them.

What it does

nc -z performs a scan/connect to a port and exits without sending data: exit 0 if the TCP handshake succeeds, non-zero otherwise. Combined with -w (timeout) and a retry loop it is the canonical "wait until the database/API is listening" gate before tests run.

Common usage

Terminal
nc -z -w 3 localhost 5432 && echo "port open"
# Wait-for-port loop:
until nc -z -w 2 db 5432; do echo "waiting for db"; sleep 1; done
nc -z -v localhost 8080        # verbose: prints open/closed
nc -z -w 5 host 80 || exit 1   # gate the step on the port
# bash builtin alternative (no netcat needed):
timeout 30 bash -c 'until (echo > /dev/tcp/db/5432) 2>/dev/null; do sleep 1; done'

Options

FlagWhat it does
-zZero-I/O: just test the connection, send nothing
-w <secs>Timeout for connect (and overall)
-vVerbose - report open/closed/refused
-uProbe UDP instead of TCP (unreliable check)
exit 0 / non-zeroOpen / closed - the gate signal

Common errors in CI

The biggest trap is netcat variants: OpenBSD nc supports -z, the GNU/traditional netcat may not, and BusyBox nc (Alpine) often lacks -z entirely - "nc: invalid option -- 'z'" means a different netcat; use the bash </dev/tcp loop instead, which needs no package. -z on UDP "succeeds" even when nothing listens (UDP is connectionless), so never use nc -zu as a readiness check. Always pair -z with -w so a dropped SYN times out instead of hanging. And "port open" is not "app ready" - the process may be listening before it can serve, so a port check plus an HTTP health check is more reliable.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →