Issue with Netcat Timeout

Why does the following netcat command not time out if the attempt to connect takes longer than 3 seconds (ie: when the port isn't open)? I assumed that the -w flag would be what I needed. OS is OSX 10.9.

nc -v -z -w 3 127.0.0.1 5050

Assuming that worked, I planned to implement like this (unsure if this will work, total bash noob)

nc -v -z -w 3 127.0.0.1 5050 | /dev/null && echo "Online" || echo "Offline"

10

5 Answers

You need to redirect to /dev/null, not pipe to it. Try the following:

nc -v -z -w 3 127.0.0.1 5050 &> /dev/null && echo "Online" || echo "Offline"

On my machine, port 5050 isn't open, and I get the following:

$ nc -v -z -w 3 localhost 5050 &> /dev/null && echo "Online" || echo "Offline"
Offline
2

Since Mac OS X 10.8.x, nc has used the -G option to set the timeout for initiating a connection. This is separate from the -w option, which sets the timeout for a connection that has been made but has gone idle.

If you are trying to use nc for port scanning, i.e. nc -v -z 10.0.1.1 1-1023, it will spend over a minute trying to connect to each non-responding port unless you add a -G timeout value:

nc -v -z -G 1 10.0.1.1 1-1023

That's one second per port scanned — much more useful.

Nc: nc is usually installed already , however on some systems such as Mac OS X, the command hangs on unreachable systems without the -G option. If that does not work use the Workaround.

nc -v -z -w 3 127.0.0.1 22 &> /dev/null && echo "Online" || echo "Offline"

Mac OSX:

nc -z -G 3 127.0.0.1 22  &> /dev/null && echo "Online" || echo "Offline"

Alternative workaround option:

bash -c '(sleep 3; kill $$) & exec nc -z 127.0.0.1 22' &> /dev/null
echo $?
0
bash -c '(sleep 3; kill $$) & exec nc -z 1.2.3.4 22' &> /dev/null
echo $?
143

(examples illustrate connecting to port 22 ssh over a good and bad host example, use the $? to determine if it reached the host with the sleep time of 3 seconds)

Alternatively For Mac Users (mainly) etc, you can use the command in the script like so :

    # -- use NMAP, if not avail. go with nc --
    if command -v nmap | grep -iq nmap ; then
        nmap ${ip} -PN -p ${ssh_port} | grep -iq "open"
        res=$?
    elif command -v nc | grep -iq nc ; then
        # -- run command if fails to complete in 3 secs assume host unreachable --
        ( nc -z ${ip} ${ssh_port} ) & pid=$!
        ( sleep 3 && kill -HUP $pid ) 2>/dev/null & watcher=$!
        if wait $pid 2>/dev/null; then
            pkill -HUP -P $watcher
            wait $watcher
            # -- command finished (we have connection) --
            res=0
        else
            # -- command failed (no connection) --
            res=1
        fi
    else
        echo "Error: You must have NC or NMAP installed"
    fi

    if [[ ${res} -lt 1 ]] ;then
        success=1
        echo "testing  => $ip SUCCESS connection over port ${ssh_port}"
        break;
    else
        echo "testing => $ip FAILED connection over port ${ssh_port}"
    fi
4

There is an old bug report about this on debian () and still having the same behavior in Debian GNU/Linux 7.7 (wheezy)

I found a "solution" to this: installing the openbsd version of nc:

apt-get install netcat-openbsd
2

On Mac OS X (10.14.6) the -w 3 parameter is somehow ignored.

The workaround I found is: timeout 3 nc -vz 10.18.50.134 23

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest