我正在尝试编写一个简单的Bash脚本,它在监听端口,并用一个简单的HTTP响应进行回复。我的具体问题是,我不确定端口是否可用,如果绑定失败,我会一直尝试下一个端口,直到绑定成功。
到目前为止,我认为最容易实现这个功能的方式是:
for (( i=$PORT_BASE; i < $(($PORT_BASE+$PORT_RANGE)); i++ ))
do
if [ $DEBUG -eq 1 ] ; then
echo trying to bind on $i
fi
/usr/bin/faucet $i --out --daemon echo test 2>/dev/null
if [ $? -eq 0 ] ; then #success?
port=$i
if [ $DEBUG -eq 1 ] ; then
echo "bound on port $port"
fi
break
fi
done
我在这里使用的是来自Ubuntu软件包中的netpipes的faucet
。
问题在于,如果我只是将“test”打印到输出中,curl
会抱怨非标准的HTTP响应(错误代码18)。这是公平的,因为我没有打印HTTP兼容的响应。
如果我用echo -ne "HTTP/1.0 200 OK\r\n\r\ntest"
替换echo test
,curl仍然会抱怨:
user@server:$ faucet 10020 --out --daemon echo -ne "HTTP/1.0 200 OK\r\n\r\ntest"
...
user@client:$ curl ip.of.the.server:10020
curl: (56) Failure when receiving data from the peer
我认为问题出在faucet
打印响应和处理连接的方式上。例如,如果我在服务器端使用netcat
,那么curl就能正常工作:
user@server:$ echo -ne "HTTP/1.0 200 OK\r\n\r\ntest\r\n" | nc -l 10020
...
user@client:$ curl ip.of.the.server:10020
test
user@client:$
我很乐意在我的主脚本中用
netcat
代替faucet
,但问题是我想生成一个独立的服务器进程,以便能够从同一个基础shell运行客户端。faucet
有一个非常方便的--daemon
参数,因为它分叉到后台,我可以使用$?
(退出状态码)来检查绑定是否成功。如果我想使用netcat
实现类似的目的,我将不得不使用&
进行分叉,而$?
将无法工作。有人知道为什么在这种特殊情况下
faucet
没有正确响应吗?或者能否提出解决这个问题的建议。我既没有与faucet
也没有与netcat
结婚,但希望使用bash或其实用程序实现解决方案(而不是编写其他脚本语言,如Perl或Python)。
(())
中不需要使用$(())
:for (( i=PORT_BASE; i < PORT_BASE+PORT_RANGE; i++ ))
。您还应该在faucet
命令中使用printf
,因为-n
和-e
选项的支持取决于echo
的实现。通过 Wireshark 监视流量,我看到faucet
出于某种原因发送了RST
。 - Dennis Williamson