Issue with netcat timeout
Asked Answered
G

5

27

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"

Gianna answered 13/6, 2014 at 5:42 Comment(10)
When I try it, I immediately get an error response because the port isn't open. Are you sure it's not open on your host? If it is, then that's why it isn't timing out, because it actually connected.Feeding
Weird, it only appears to be happening on a specific port... I was trying to use this to monitor if a specific service is running on my machine from a remote location or network. That service is not currently running, but the netcat doesn't seem to time out, the process just hangs. Any thoughts?Gianna
Are you running any kind of firewall? What does "iptables -L" show you?Feeding
I am using OSX and my firewall is turned off. It explicitly states "All connections are allowed to this computer". There is no native 'iptables' command in OSX.Gianna
netcat apparently acts different on different platforms (philandstuff.com/2013/05/17/statsd-netcat.html). I'm on linux. Can you run tcpdump while you run this command to see if the expected behavior is occurring?Feeding
Assuming port 5050 isn't open, you should see a SYN packet from localhost, followed by a RST packet from port 5050.Feeding
pastebin.com/DJV4B04m Will filtering like this contain the info required? Without filtering by port 5050 it's pretty much impossible to interpret the log... Also, just fyi, I have just noticed that the request eventually times out on the remote host, but it's taking over a minute... completely stumped here.Gianna
You probably want to look at the lo interface (or whatever it's called on OSX). Any traffic to 127.0.0.1 won't show up on en0.Feeding
This may be an OSX thing. See this other article: #18579065Feeding
Let us continue this discussion in chat.Feeding
F
38

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
Feeding answered 13/6, 2014 at 5:47 Comment(2)
Thanks for that! Out of curiosity why is the & needed when redirecting?Gianna
nc dumps out the verbose output to stderr, so if you just want to see the "Online" and "Offline", you need to use &> to tell bash to redirect both stdout and stderr to /dev/null. If you get rid of the -v, you can just say nc -z -w 3 localhost 5050 && echo "Online" || echo "Offline"Feeding
C
24

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.

Cyndi answered 29/3, 2020 at 18:29 Comment(0)
D
12

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
Diao answered 9/5, 2019 at 15:30 Comment(4)
On Mac just use the -G option. nc -z -G 3 127.0.0.1 22Greenback
i had some luck using timeout command. timeout 1 nc ...Bobinette
@Bobinette I think you are good with the -G for mac, you shouldn't need anything else, what issue are you trying to solve?Diao
to be cross platform support both mac and linuxBobinette
Y
5

There is an old bug report about this on debian (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=97583) 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
Yonatan answered 11/11, 2014 at 19:25 Comment(2)
I had this problem with nc on macOS 10.13.4. Installing (gnu) netcat with Homebrew fixed it...Reflection
That bug was fixed in 2001, so Debian 3.0 (Woody) and later should not have suffered it. The problem with the question, as noted in the accepted answer, was syntax related (nc … |/dev/null won't work because /dev/null is not executable, nc … >/dev/null works fine). That said, the fix was applied on Debian specifically and upstream netcat still likely has it (current Debian uses netcat 1.10-41.1, the fix was in 1.10-18, the dash refers to the Debian build, using patches to modify the upstream version), so I could understand OS X still having that issue.Palpitate
O
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

Orvilleorwell answered 12/12, 2019 at 14:9 Comment(2)
-w is used to set the timeout after connection. -G option is used to set the timeout before connection. This is a better workaround for macOS users: nc -G 3 xxx.xxx.xxx.xxx 5050 source: https://mcmap.net/q/505206/-nc-netcat-on-mac-os-x-10-8-4-gets-stuckParch
timeout as per expectation. I guess will use both 'timeout' and '-G'. The latter is taking a bit more time. However, the conclusion is that '-w' switch does not work at all!Opportina

© 2022 - 2024 — McMap. All rights reserved.