![通过 TCP 公开 awk(inetd、socat 等)](https://linux22.com/image/48110/%E9%80%9A%E8%BF%87%20TCP%20%E5%85%AC%E5%BC%80%20awk%EF%BC%88inetd%E3%80%81socat%20%E7%AD%89%EF%BC%89.png)
我正在使用 awk,我想通过 TCP 套接字公开它。
起初我尝试过,但使用 micro inetd 失败了。考虑到问题可能出在处理回车符/换行符的方式上,我决定尝试切换到 socat。
通过 socat 使用远程命令非常简单:
socat TCP4-LISTEN:9000 EXEC:/bin/cat
socat TCP4-LISTEN:9000 SYSTEM:"/bin/python -i"
这两个工作
但是,当使用简单的 awk 命令尝试相同的操作时(例如 `awk '{print NR}' 来逐步计算收到的行数),当从同一台机器上的另一个 shell 与 socat 连接时,我没有得到任何信息。
我尝试了很多东西(其中一些因语法错误而失败,这对我来说有点晦涩。我什至无法尝试 strace socat 来查看到底正在执行什么,因为实际的命令执行被委托给 shell) :
socat TCP4-LISTEN:9000 SYSTEM:"/usr/bin/awk '{print NR}'"
socat TCP4-LISTEN:9000 SYSTEM:'/usr/bin/awk "{print NR}"'
socat TCP4-LISTEN:9000 SYSTEM:'/usr/bin/awk "{print\ NR}"'
我还创建了一个小脚本/tmp/testawk
#! /bin/sh
/usr/bin/awk '{print NR}'
(也有一个 exec 变体)
#! /bin/sh
exec /usr/bin/awk '{print NR}'
这两个都在本地工作,但是在调用时
socat TCP4-LISTEN:9000 EXEC:/tmp/testawk
它不会发回输出
认为问题可能是 stdin/stdout 句柄的继承和/或再次处理 crlf ...我也尝试过:
socat TCP4-LISTEN:9000 EXEC:/tmp/testawk,nofork
socat TCP4-LISTEN:9000,crnl EXEC:/tmp/testawk
socat TCP4-LISTEN:9000 EXEC:/tmp/testawk,crnl
socat TCP4-LISTEN:9000,crnl EXEC:/tmp/testawk,crnl
我发现还有人抱怨类似的问题,但显然它未能引起任何关注
知道出了什么问题吗?
答案1
awk 正在打印到标准输出,当它指向终端时,它是行缓冲的,如果不是,则完全缓冲;这意味着您应该在填充缓冲区后获得输出,即它已打印(例如)4KB。
您可以通过发送大量输出来测试这一点(例如使用 yes 程序);要修复你应该: - 取消缓冲 awk 的标准输出(参见例如https://unix.stackexchange.com/a/25375/63847) - 使用来自发送者的 shutdown(2) 系统调用(丑陋)
欢迎任何更好的解决方案
答案2
您可以告诉socat
将 pty 与awk
程序关联起来;这会强制awk
以行缓冲模式运行,并且您会立即获得所需的响应。
下面是监听 9000 端口的命令行:
socat TCP4-LISTEN:9000 SYSTEM:'/tmp/awk.sh',pty,echo=0
这是脚本的内容/tmp/awk.sh
:
#!/usr/bin/awk -f
#
BEGIN { print "This is the awk socket" }
{ print NR, $0 }
END { print "All done" }
示例运行:
$ nc -vvv otherhost 9000
otherhost [192.168.1.15] 9000 (?) open
This is the awk socket
hello world
1 hello world
how are you
2 how are you
boo
3 boo
^C sent 28, rcvd 61