使用netcat时遇到超时问题

25
为什么以下的 netcat 命令在连接尝试需要超过 3 秒时(即端口未打开时)没有超时?我认为 -w 标志是我需要的。操作系统是 OSX 10.9。
假设这个命令可以工作,我计划像这样实现(不确定是否有效):
nc -v -z -w 3 127.0.0.1 5050 | /dev/null && echo "在线" || echo "离线"

当我尝试它时,立即收到错误响应,因为端口没有打开。你确定你的主机上没有打开它吗?如果是这样,那么它不会超时,因为它实际上已经连接了。 - CDahn
奇怪,它似乎只发生在特定的端口上...我试图使用它来监视远程位置或网络上我的计算机是否正在运行特定的服务。该服务目前未运行,但netcat似乎没有超时,进程仅挂起。有什么想法吗? - anditpainsme
你是否运行任何类型的防火墙?"iptables -L" 显示了什么? - CDahn
我正在使用OSX,我的防火墙已关闭。它明确说明“所有连接都允许连接到此计算机”。在OSX中没有本地的“iptables”命令。 - anditpainsme
过滤器是否像这样包含所需的信息?如果不按5050端口过滤,解释日志几乎是不可能的...此外,只是提供信息,我刚刚注意到请求最终在远程主机上超时,但需要超过一分钟...完全被卡住了。 - anditpainsme
显示剩余5条评论
5个回答

37

你需要重定向到 /dev/null,而不是将其作为管道使用。请尝试以下操作:

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

在我的电脑上,5050端口没有开放,并且我得到了以下提示:

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

1
谢谢!出于好奇,为什么重定向时需要使用 & 符号? - anditpainsme
2
nc会将详细输出转储到stderr,因此如果您只想看到“在线”和“离线”,则需要使用&>告诉bash将stdout和stderr重定向到/dev/null。如果您去掉了-v,则可以只使用nc -z -w 3 localhost 5050 && echo "Online" || echo "Offline"。 - CDahn

19
自Mac OS X 10.8.x以来,nc 使用 -G 选项设置建立连接的超时时间。这与 -w 选项分开设置一个已建立但闲置的连接的超时时间。

如果您想使用 nc 进行端口扫描,即 nc -v -z 10.0.1.1 1-1023,它将花费超过一分钟的时间尝试连接每个未响应的端口,除非您添加 -G 超时值:

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

每个扫描的端口仅需一秒钟,更加实用。


11

Nc:nc通常已经安装,但在某些系统上(如Mac OS X),如果没有-G选项,该命令将无法访问不可达的系统。如果这不起作用,请使用解决方法。

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"

替代解决方案选项:

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

(示例说明连接到端口22 ssh的好和坏主机示例,使用$?来确定是否在3秒的睡眠时间内到达了主机)

或者对于Mac用户(主要是),您可以像这样在脚本中使用命令:

    # -- 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

1
在 Mac 上只需使用 -G 选项。nc -z -G 3 127.0.0.1 22 - Chris
我曾经使用 timeout 命令 取得了一些成功。timeout 1 nc ... - Fred.W
@Fred.W 我认为你对于mac上的-G很熟悉,你不需要其他东西,你想要解决什么问题? - Mike Q
要跨平台支持Mac和Linux。 - Fred.W

5

关于这个问题,在Debian上有一个旧的bug报告(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=97583),在Debian GNU/Linux 7.7(wheezy)中仍然存在相同的行为。

我找到了一个“解决方案”:安装OpenBSD版本的nc:

apt-get install netcat-openbsd

2
我在macOS 10.13.4上使用nc时遇到了问题。通过Homebrew安装(gnu) netcat解决了这个问题... - Motsel
该漏洞已于2001年修复,因此Debian 3.0(Woody)及更高版本不应受到影响。正如接受的答案中所指出的问题,与语法有关(nc … |/dev/null无法工作,因为/dev/null不可执行,nc … >/dev/null可以正常工作)。话虽如此,修复程序是专门针对Debian进行的,上游netcat仍然可能存在该问题(当前Debian使用netcat 1.10-41.1,修复程序在1.10-18中,破折号指的是Debian构建,使用补丁修改上游版本),因此我可以理解OS X仍然存在该问题。 - Adam Katz

1
在Mac OS X(10.14.6)中,-w 3参数会被忽略。
我找到的解决方法是:timeout 3 nc -vz 10.18.50.134 23

3
-w 用于设定连接后的超时时间。-G 选项用于设定连接前的超时时间。这是针对 macOS 用户的更好解决方法:nc -G 3 xxx.xxx.xxx.xxx 5050来源: https://dev59.com/THbZa4cB1Zd3GeqPFWMA#35141831 - Aditya Purandare
1
按预期超时。我猜会同时使用“timeout”和“-G”。后者需要更多时间。然而,结论是“-w”开关根本不起作用! - anup

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接