
干运维这行的谁还没用过几次nc呢。很多刚接触Linux的朋友第一次听说nc是在查“怎么测试某个IP的端口通不通”的时候搜了一圈发现大家都在提nc然后跑去CentOS 7上一敲nc -vz 192.168.1.10 3306结果要么报command not found要么装完之后用起来跟教程里写的不太一样。这背后的坑其实值得花几分钟理清楚。nc全名叫netcat网上喜欢叫它“网络瑞士军刀”。这名字不是白叫的它能在TCP和UDP协议栈上干大量事情从最基础的端口探测、端口监听到传文件、做简易聊天室、端口转发都能在一条命令里搞定。没有图形界面不需要装一堆依赖一个二进制文件就能解决很多网络排查问题这就是它存在的价值。这篇东西我会从CentOS 7上怎么正确安装nc开始把所有常用场景拆开来讲最后再把实际用的时候最容易踩的坑列一遍。这篇内容正好适合刚接触Linux服务器运维、需要在CentOS 7上做网络调试和端口排查的朋友也适合那些已经用了nc一段时间、但每次都是复制粘贴命令、不清楚参数含义的人。1. 装nc之前先把“版本差异”这件事弄明白很多教程讲nc都是拿Debian系的Linux举例子但同样的命令到了CentOS 7上表现还真不一样。这就要从CentOS 7的默认软件源说起。1.1 此nc非彼ncnetcat、nc、ncat的关系先澄清一个很容易绕晕的点。netcat是一个“一类工具”的名字最早由Hobbit在1996年发布功能是读写TCP或UDP网络连接。后来因为开源协议和功能演进市面上出现了好几个主流分支传统netcatOpenBSD版很多人说“正统nc”一般指这个支持-z、-e等参数体积非常小行为干净利落。GNU netcatDebian系默认装的那个版本重写了大部分代码参数风格和前两者有差异。ncatNmap项目自己写的netcat实现功能更强支持SSL、支持代理、支持连接持久化现代感更足。CentOS 7自带的软件源里yum install nc装的是nmap-ncat这个包。也就是说你在CentOS 7上敲nc实际执行的是ncat。1.2 为什么CentOS 7上直接敲nc会报command not foundCentOS 7最小化安装的时候默认不会装nc。很多教程说“CentOS自带nc”那说的是比较老的CentOS 6或者某些完整安装模式。到了7不带图形界面的最小化安装是非常精简的很多网络排查工具都得自己装。正确的安装指令是yum install -y nc如果提示找不到包先执行yum clean all yum makecache再装一次。装完验证nc -h出现ncat的帮助信息就说明装好了。注意看帮助信息第一行很可能写着Ncat 7.50这个版本号就是ncat的版本别奇怪。提示如果你之前用过Ubuntu上的nc再用CentOS 7上的nc会感觉“参数对不上”最典型的是-q选项在ncat里的用法和传统netcat不太一样。这个后面讲文件传输时会重点说。2. 安装与基础配置的两种路径既然已经知道CentOS 7上装nc实际是装ncat那安装方式上其实有两套思路分别适合不同的场景。2.1 最快路径yum直接安装这是绝大多数场景下的首选。好处是依赖全部自动处理系统里也不会有乱七八糟的文件残留。yum install -y nc安装完成后看看到底装了什么rpm -qa | grep ncat rpm -ql nmap-ncat | grep binrpm -ql能列出一个包安装的所有文件你会看到nc和ncat这两个可执行文件被放到了/usr/bin/目录下而且是硬链接的关系。这里有一个实际体验上的区别yum装出来的ncat功能很全支持TCP、UDP、SSL等协议。但对于只是想“测试某个端口通不通”的场景这个版本是绰绰有余的。2.2 源码编译安装传统netcat如果你需要的是原汁原味的传统netcat比如你要跟别的机器上老版本的nc做兼容性测试或者需要-e参数来执行程序yum方式就满足不了了。这时候需要源码编译。先从官网下载OpenBSD netcat的源码或者从GitHub拉取镜像仓库wget https://github.com/.../netcat.tar.gz tar -zxvf netcat.tar.gz cd netcat ./configure --prefix/usr/local make make install编译完成后系统里会出现两个nc一个是/usr/bin/ncyum装的ncat一个是/usr/local/bin/nc源码装的OpenBSD netcat。注意这里有个优先级问题/usr/local/bin通常排在/usr/bin前面所以直接敲nc很可能执行的是源码装的这个。可以用which nc确认。2.3 两种安装方式怎么取舍说实话对绝大多数运维排查场景来说yum install nc就够了。原因有三点yum装的ncat对-z、-v、-w这些常用参数支持得非常好。卸载、升级、依赖管理都省心。大部分网上教程的命令在ncat上跑不会出大问题。源码编译适合以下几种情况你需要在新版本ncat里没有的某个特定行为你需要在离线内网环境安装工具没法用yum源你在做安全测试需要精确控制netcat的每一个参数细节我的建议是先用yum装真遇到功能短板再考虑源码编译。别一上来就编译CentOS 7上的gcc、make这些构建工具也要装一堆为了一个网络工具去折腾构建链性价比不高。3. nc最常用的几个实战场景先看一个概念nc基本就是在一个终端里读取数据、写入数据本质上就是把标准输入接到网络连接上再把网络连接的数据打印到标准输出。理解了这一点后面所有玩法都是围绕“怎么操作这个输入输出”展开的。3.1 TCP端口探测最核心的用法这是用得最多的场景。服务器上线前业务方说“帮我看看我这台机器能不能连上数据库的3306端口”你第一反应就是nc。nc -vz -w 3 192.168.1.10 3306参数拆开看-vverbose显示详细过程连接成功失败都有提示-zzero I/O模式只扫描端口不发送实际数据-w 3超时时间3秒防止卡住太长时间执行后如果显示Connection to 192.168.1.10 3306 port [tcp/mysql] succeeded!那端口就是通的。如果显示No route to host或Connection refused则需要排查网络和防火墙。Connection refused和No route to host的区别值得记一下前者代表IP能通但目标端口没有服务在监听后者代表IP层面就不通可能是防火墙拦截、路由问题或者机器本身不在线。也可以一次扫多个端口nc -vz -w 2 192.168.1.10 22 80 443 3306这种连续扫多个端口的写法在日常排查时很实用一次拿到所有结果不需要反复执行。3.2 UDP端口探测和监听UDP场景排查起来比TCP麻烦因为UDP没有握手概念你发一个包过去对方监听没监听很多时候是“沉默”的。nc在UDP模式下能做有限的检测。nc -vz -u -w 2 192.168.1.20 53这里的-u就是走UDP协议。但要注意这种探测的准确率不如TCP。很多情况下UDP端口明明有服务在监听但探测端显示Connection refused这是目标主机回了一个ICMP端口不可达消息说明端口确实没开如果没有任何回包则可能是通的也可能是被防火墙静默丢包了只能结合其他手段综合判断。监听UDP端口则常用在验证某个服务有没有正确发包出来nc -u -l 10086执行后任何向这台机器10086端口发送的UDP数据都会打印出来。这个在调试自定义协议、验证日志采集器是否发数据时很好用。3.3 文件传输隔空取物的极简方案不需要scp不需要搭建FTP两台机器只要能网络互通nc就能直接传文件。接收端先执行nc -l 9999 received_file.zip发送端再执行nc 192.168.1.10 9999 myfile.zip传输完成后发送端会看到连接关闭接收端的文件也就完整保存了。原理其实特别简单发送端把文件内容通过标准输入喂给ncnc把数据通过网络发出去接收端的nc把收到的数据写到标准输出然后重定向到文件里。传目录的话要先打包tar -czf - /path/to/dir | nc 192.168.1.10 9999接收端nc -l 9999 | tar -xzf -这里有一个在CentOS 7上必须要记住的差异用-l监听时传统netcat会在连接建立后马上把标准输入里收到的数据发出去。但ncat在文件传输场景下连接建立后默认要等标准输入EOF文件末尾才发送这个行为差别可能导致老教程里的命令在CentOS 7上表现不对。更稳妥的做法是加上-q 0表示传输完立即关闭连接nc -q 0 -l 9999 received_file.zip如果发现传文件传完但没有结束多半就是-q参数的问题。3.4 简易端口转发与联调测试nc还能做简单的端口转发。比如本地的某个服务只监听在127.0.0.1但你想让其他机器也能访问而我不想配复杂的iptables规则可以用nc临时做个转发mkfifo /tmp/nc_fifo nc -l 8080 /tmp/nc_fifo | nc 127.0.0.1 9000 /tmp/nc_fifo这条命令的原理是用一个FIFO文件把两个nc连接串起来一个nc监听8080端口收到数据后通过管道转给另一个nc后者把数据发到9000端口返回的数据再从FIFO带回给第一个nc。这样外部机器访问本机8080就等于访问了本机9000的服务。这个用法有个明显的短板它是一次性的连接断开后命令就结束了。要做持久化的端口转发还是得用iptables或者socat。但作为临时联调、应急用的工具这一行命令已经能解决很大问题了。3.5 简易“聊天室”了解一下nc还能当作临时的文本通信工具这在调试网络时能直观地验证双向通信是否正常。服务端nc -l 12345客户端nc 192.168.1.10 12345两边连上之后任何一端输入文字按回车另一端就能实时看到。注意这个只是原始文本流没有任何加密和身份认证实际生产环境不要这么用只在临时调试时有点意义。有一种场景特别适合用它验证两台机器间的网络策略是否允许双向通信。如果TCP端口探测只能证明连接能建立那用nc聊天能直接看到数据双向流通对于确认防火墙是否只放行了单向流量很有帮助。4. 一个可以直接抄作业的端口检查脚本nc单独用已经够了但运维不是一次只查一个端口更多时候是一次性检查一台机器的多个端口、多台机器的同一个端口。这时候把nc封装进脚本里效率提升非常明显。4.1 外网连通性批量检查最简单的场景检查一批远端服务器的某个端口是否开放。#!/bin/bash # 批量检查端口连通性 hosts(192.168.1.10 192.168.1.11 192.168.1.12) port$1 if [ -z $port ]; then echo Usage: $0 port exit 1 fi for host in ${hosts[]}; do if nc -z -w 3 $host $port /dev/null 21; then echo $host:$port is open else echo $host:$port is closed or unreachable fi done这里把nc -z -w 3的-v输出重定向到/dev/null因为脚本里不需要看nc自身的报错只需要通过nc的退出码$?来判断端口状态成功就是0失败是非0。这种写法可以让脚本输出很干净方便直接对接告警平台。4.2 单机多端口遍历检查跟上面相反有时候是固定一台机器要检查多个服务端口是否都在监听。这种情况适合用嵌套循环#!/bin/bash # 检查本机关键端口状态 ports(22 80 443 3306 6379 8080) for p in ${ports[]}; do if nc -z -w 2 127.0.0.1 $p /dev/null 21; then echo port $p is open else echo port $p is closed fi done这里有个细节检查本机端口时用127.0.0.1比用本机IP地址更准确。原因很简单很多服务只监听了回环地址用本机IP去连反而会失败容易误判。另外用nc -z去探测本机端口走的是TCP握手比用ss -tlnp看监听列表更能反映“实际能不能建立连接”这一层。4.3 脚本里别忘了写超时脚本里所有nc调用都建议显式加-w参数。如果目标IP不可达不加-w的话nc可能会挂很久。这种超时时间过长的现象在批量检查多台机器时会非常明显一台机器网络不通脚本卡在那一台上后面的机器全等着。-w参数对-z模式的生效逻辑是TCP连接如果不能在设定时间内完成就判定失败。设成-w 3或-w 5都是合理的选择。如果目标在公网建议设大一点比如-w 10避免误报超时。5. 一堆踩过的坑和排查技巧5.1 装了nc但执行报错、退出码异常CentOS 7上最常见的问题有两个nc: Protocol not available这个报错一般出现在UDP模式-u要么是内核没有加载对应协议模块要么是容器环境里没有给到NET_RAW权限。排查时先试nc -u -l监听本地端口如果也报同样的错大概率是环境权限问题。nc: Permission denied这个一般出现在防火墙拦截的场景或者SELinux限制。在CentOS 7上如果SELinux是Enforcing模式某些非标准端口访问会被SELinux策略拦下来。排查时可以临时setenforce 0试试如果问题消失就是SELinux策略问题需要调整策略而不是关闭nc。5.2 端口探测显示closed但服务明明在跑这个太经典了。遇到这种矛盾的结论先别急着怀疑nc冷静地按步骤排查先确认服务监听地址。用ss -tlnp | grep 3306看监听的是0.0.0.0:3306还是127.0.0.1:3306。只监听127.0.0.1的话外部IP连不上是正常的。确认服务绑定的IP是否和探测目标一致。有时候机器有多个网卡服务监听在管理网卡上你拿业务网卡的IP去探测自然是失败。检查防火墙。CentOS 7默认用的是firewalld而不是老的iptables。systemctl status firewalld看一下是否在运行如果开着就检查firewall-cmd --list-all的开放端口列表。再看SELinux。这些步骤都走完最后才轮到怀疑nc本身的问题。大部分所谓“nc探测结果不准”的结论都是因为前面没有排查完就急于下结论。5.3 文件传输传完卡住不退出在ncat上特别常见。接收端nc -l 9999 file.txt传完大文件后命令迟迟不退出。这是因为ncat在默认情况下接收端不知道发送端什么时候结束它要等网络连接关闭收到FIN才会退出。如果发送端没有显式关闭接收端就会一直挂着。解决方案是接收端加-q 0参数含义是EOF后立即退出nc -q 0 -l 9999 file.txt发送端也可以加-q 0表示数据发送完成后立即关闭连接这样接收端也能感知到结束。5.4 老装不上、源有问题有些内网机器没法访问外网源yum install nc会卡在下载阶段。解决办法是把软件包下载下来拷进内网装在外网机器上执行yum install --downloadonly --downloaddir/tmp/nc_pkg nc把/tmp/nc_pkg目录下的rpm包拷到内网机器上然后rpm -ivh /tmp/nc_pkg/*.rpm--downloadonly是yum的一个参数只下载不安装配合--downloaddir指定保存目录非常好用。注意CentOS 7的yum本身可能不带downloadonly插件需要先装yum-plugin-downloadonlyyum install -y yum-plugin-downloadonly5.5 用nc测完端口记得考虑卸载nc本身是一把双刃剑。它能干的事太多如果服务器上跑着业务却留着一个可以任意收发网络数据的工具安全隐患是实打实的。常规建议是排查完问题如果业务不需要长期用nc就卸掉yum remove -y nc或者严格限制系统用户的执行权限。总之这类网络调试利器用的时候痛快收尾的时候也得干净。5.6 那些容易被忽略的小参数-n不解析域名直接用IP地址。探测IP时建议加上能大幅缩短响应时间不然nc每次连接都要反向解析目标IP的域名网络环境不好时会卡很久。-C发送CRLF换行。如果是跟HTTP服务交互比如想手动发一个HTTP请求来验证服务是否正常printf配合-C会比较方便。-k保持监听。ncat支持加-k让监听端口在处理完一个连接后不退出继续等待下一个连接。传统netcat不支持。这个参数在测试并发连接时很有用。我把这些参数列成一个简单的速查表方便快速参考需求命令示例关键参数说明TCP端口探测nc -vz -w 3 192.168.1.10 3306-z零I/O模式-w超时-v显示详情UDP探测nc -vz -u -w 2 192.168.1.20 53-u切到UDP监听端口收文件nc -q 0 -l 9999 file.zip-l监听-q 0EOF后退出发送文件nc -q 0 192.168.1.10 9999 file.zip发送端同样加-q 0快速扫描多个端口nc -vz -n 192.168.1.10 22 80 443-n不做域名解析抓UDP数据包nc -u -l 10086监听UDP打印收到的数据6. 关于nc我最后想多说两句从我自己的使用感受来说nc最值钱的地方不在于功能多花哨而在于它足够简单、足够原始。排查网络问题的时候很多花哨的图形工具反而会掩盖问题本质而nc就一道命令下去通就是通不通就是不通没有任何中间地带。这种确定性在数据中心割接、网络策略变更、服务上线验证的深夜里能帮你省下大把的时间。另外想建议的是刚接触Linux服务器的朋友可以刻意多练练nc的各个参数不要只记一个组合。今天用-z扫端口明天用-l收文件后天用-u调试UDP。参数熟不熟直接影响排查思路的流畅度。就实用主义的角度看不用把nc的每个冷门功能都背下来。除了上文提到的这些场景剩下的大部分功能都有更专业的替代工具比如socat做端口转发更强tcpdump抓包分析更强curl测HTTP接口更强。nc的定位是“快速、应急、通用”理解了这一点你就能在合适的场景里把它的作用发挥到最大。