我正在尝试使用 netcat 在 bash 中创建一个简单的服务器,它接受来自远程机器的命令并返回一些数据,我知道其他语言更适合这项任务,但我正在尝试找出在 bash 中执行此任务的最佳方法。
因此要求是:
- 监听传入的连接(不需要同时处理多个连接)
- 每次处理一行从远程机器接收到的命令
- 将每个命令的输出返回到远程机器
- 能够从服务器端终止连接
我已经创建了一个可以工作并满足所有要求的东西,但它使用临时文件来存储请求并tail
读回它们。一段时间以来,我一直在尝试仅使用管道和输入/输出重定向或 FIFO 来实现相同的结果,但到目前为止还没有成功,所以我想问一下是否有人知道一些可以在这里使用的技巧。
我当前的代码(使用tail
临时文件,我都想避免):
#!/bin/bash
request=/tmp/bashsrvR
function HandleCommand {
echo "received command: $1"
[ "$1" = "exit" ] && return 1
return 0
}
while :; do
>$request
tail -f $request 2>/dev/null | while read line; do
HandleCommand $line || break
done | nc -l -c -p 5000 >$request
done
答案1
FIFO 是解决方案。这是你以一种快速而粗略的方式修改的代码:
#!/bin/sh
request=/tmp/bashsrvR
rm "$request"
mkfifo "$request"
HandleCommand () {
echo "received command: $1"
[ "$1" = "exit" ] && return 1
return 0
}
while :; do
while read line; do
HandleCommand "$line" || break
done <"$request" | nc -l -p 5000 >"$request"
done
这里没有什么sh
不能做的,所以我用它代替了bash
,以实现便携性。而且我引用正确。
脚本会检测,exit
但nc
服务器和/或客户端可能不会立即退出。不同的实现nc
nc
。我在 Debian 中使用传统(不是 BSD)进行了测试。我将nc
其用作服务器和客户端。然后运行服务器导致-q 1
交互式客户端(即nc
从 tty 读取)在发送后立即终止exit
。一般来说,行为也取决于客户端。比较BSDnc
不会在 EOF 处终止。
在我看来socat
是一个更好的工具作为类似情况的服务器:
socat TCP-LISTEN:5000,fork EXEC:'/path/to/inner_script',stderr,pty,echo=0
在这里,inner_script
应该只从其标准输入读取,写入其标准输出,完成后直接退出。脚本不应该关心网络连接,这是 的socat
工作。简化为以下代码片段的代码可以充当inner_script
:
#!/bin/sh
HandleCommand () {
echo "received command: $1"
[ "$1" = "exit" ] && return 1
return 0
}
while read line; do
HandleCommand "$line" || exit
done
socat
处理连接和管道;您原来的重定向问题已自动解决。socat
从外部脚本运行并将保留inner_script
为单独的文件。
注意:fork
允许socat
为许多客户提供服务,因此它充当while
原始代码的外循环。但fork
也允许socat
为许多客户提供服务同时地. 你可能想要或者不想要这个。