我想知道如何让 shell 脚本监听某个端口(也许使用 netcat?)。希望当消息发送到该端口时,脚本会记录该消息,然后运行一个函数。
例子:
计算机 1 在后台运行该脚本,该脚本向传入流量打开端口 1234
计算机2向计算机1的1234端口发送消息“hello world”
计算机 1 上的脚本将消息“hello world”记录到变量 $MESSAGE
现在变量 $MESSAGE 已设置,脚本运行函数
我该怎么做呢?
答案1
应该可以用socat
.
编写这样一个脚本“getmsg.sh”以通过标准输入接收一条消息:
#!/bin/bash
read MESSAGE
echo "PID: $$"
echo "$MESSAGE"
然后运行此socat
命令为端口 7777 上的每个 tcp 连接调用我们的脚本:
socat -u tcp-l:7777,fork system:./getmsg.sh
从另一个 shell 发送测试消息:
echo "message 1" | netcat localhost 7777
答案2
UCSPI-TCP方式
除了 netcat 之外还有其他工具集。以下是其中一些的使用方法。他们都假设存在一个service
运行您的脚本func
,无论它是什么:
#!/bin/sh 读取时 -r MESSAGE 做 echo 1>&2 "${TCPREMOTEIP}" "${TCPREMOTEPORT}" rx "${MESSAGE}" 功能 完毕
TCPREMOTEIP
和环境变量TCPREMOTEPORT
由 UCSPI-TCP 协议定义。
该脚本是使用各种工具集作为每个 TCP 连接的单独进程生成的。接下来,这些工具将在一个简短的脚本中使用。这样的脚本通常称为run
,是人们在 daemontools 系列服务管理器下运行它们的方式。当然可以直接调用它们。
伯恩斯坦 ucspi-tcp
使用 Daniel J. Bernstein 的 ucspi-tcp,tcpserver
生成service
脚本:
#!/bin/sh -e 执行 tcpserver -v -P -R -H -l 0 0.0.0.0 7777 ./service
Bernstein ucspi-tcp 有支持 IPv6 的增强版本。 Erwin Hoffmantcpserver
尝试将 IPv4 和 IPv6 合二为一(如果操作系统支持,有些操作系统不支持)并生成脚本service
:
#!/bin/sh -e 执行 tcpserver -v -P -R -H -l 0 ::0 7777 ./service
Bercot s6-网络、s6 和 execline
使用 Laurent Bercot 的 s6 网络,分别s6-tcpserver4
处理s6-tcpserver6
IPv4 和 IPv6,并生成service
脚本:
#!/command/execlineb s6-tcpserver4 -v 0.0.0.0 7777 。/服务
#!/command/execlineb s6-tcpserver6 -v ::0 7777 。/服务
人们可以通过在之前的链中插入诸如s6-tcpserver-access
和 之类的工具来构建更复杂的服务器。s6-applyuidgid
./service
nosh UCSPI 工具
使用 nosh 工具集,tcp-socket-listen
侦听 TCP 套接字,如果操作系统支持,则再次同时处理 IPv4 和 IPv6,并tcp-socket-accept
依次生成脚本service
:
#!/bin/nosh tcp-socket-listen --combine4and6 :: 7777 tcp-socket-accept --verbose --localname 0 。/服务
或者在 OpenBSD 等操作系统上运行两个独立的进程:
#!/bin/nosh TCP 套接字监听 0.0.0.0 7777 tcp-socket-accept --verbose --localname 0 。/服务
#!/bin/nosh tcp-socket-监听::7777 tcp-socket-accept --verbose --localname :: 。/服务
人们可以通过在链中插入诸如ucspi-socket-rules-check
和 等工具来构建更复杂的服务器。setuidgid
#!/bin/nosh tcp-socket-listen --combine4and6 :: 7777 setuidgid 非特权用户 tcp-socket-accept --verbose --localname 0 ucspi 套接字规则检查 --verbose 。/服务
帕普 ipsvd
使用 Gerrit Pape 的 ipsvd,tcpsvd
生成service
脚本:
#!/bin/sh -e 执行 tcpsvd -v 0.0.0.0 7777 ./service
UCSPI-UDP
service
当标准输入是一个时,通用脚本可以处理溪流插座。但您没有明确指定 TCP。
虽然前面提到的一些工具包可以用来构建 UDP 服务器,其方式与使用它们构建 TCP 服务器的方式类似(参见udp-socket-listen
nosh),但使用 shell 脚本构建实际的服务程序是很棘手的,因为 shell 的内置函数不支持这种方式。当标准输入是一个时,必然能够很好地应对数据报插座。
进一步阅读
- 协议:
- 乔纳森·德博因·波拉德 (2016)。UNIX 客户端-服务器程序接口上的 gen。经常给出的答案。
- 丹尼尔·伯恩斯坦 (1996)。UNIX 客户端-服务器程序接口。 cr.yp.to。
- 工具集:
- 丹尼尔·J·伯恩斯坦。ucspi TCP协议。 cr.yp.to。
- s6 网络。洛朗·贝尔科特. skarnet.org。
- s6。洛朗·贝尔科特. skarnet.org。
- 乔纳森·德博因·波拉德 (2016)。开胃菜。 软件。
- ipsvd。格里特·帕普. smarden.org。
- 参考手册:
- 丹尼尔·J·伯恩斯坦。该
tcpserver
程序。 ucspi-tcp。 - 埃尔文·霍夫曼。
tcpserver
。 ucspi-tcp6。 fehcom.de。 s6-tcpserver4
。洛朗·贝尔科特. s6 网络。 skarnet.org。s6-tcpserver6
。洛朗·贝尔科特. s6 网络。 skarnet.org。s6-tcpserver-access
。洛朗·贝尔科特. s6 网络。 skarnet.org。s6-applyuidgid
。洛朗·贝尔科特. s6。 skarnet.org。- 乔纳森·德博因·波拉德 (2016)。
tcpserver
。 小吃指南。软件。 - 乔纳森·德博因·波拉德 (2016)。
tcp-socket-listen
。 小吃指南。软件。 - 乔纳森·德博因·波拉德 (2016)。
tcp-socket-accept
。 小吃指南。软件。 - 乔纳森·德博因·波拉德 (2016)。
ucspi-socket-rules-check
。 小吃指南。软件。 - 乔纳森·德博因·波拉德 (2016)。
setuidgid
。 小吃指南。软件。 - 乔纳森·德博因·波拉德 (2016)。
udp-socket-listen
。 小吃指南。软件。 tcpsvd
。 ipsvd。格里特·帕普. smarden.org。
- 丹尼尔·J·伯恩斯坦。该
答案3
udpsvd
这也可以通过Ubuntu/Debian 上的可用工具来完成(参见联机帮助页)以及内置到 busybox 中。例子:
# simple UDP "echo" on port 9998
udpsvd 0.0.0.0 9998 cat
替换cat
为要执行的 shell 脚本,stdin 是数据包。
使用netcat
,您可以循环运行以继续监听,并将每个数据包传递到myscript
:
while true; do nc -ul 9998 | myscript.sh; done
如果您想将所有收到的数据包作为流传递给脚本的单次调用:
# this will keep listening instead of terminating the process:
nc -kul 9998 |myscript.sh