Issue with Netcat Timeout

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
Author

Sarah Jenkins

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.