shell - 从管道的后面杀死管道中的特定进程

标签 shell process telnet

我正在编写一个 shell 脚本,它使用 telnet 连接到服务器,发送查询,然后获取单行响应以进行进一步处理。经典的解决方案是设置一个子 shell,它 echo 查询,然后运行 ​​sleep 以保持连接打开足够长的时间以便返回响应:

#!/bin/sh

SERVER_ADD=localhost
SERVER_PORT=9995

result=$( ( echo '{"op":"get","path":"access"}'; sleep 30 ) | telnet "$SERVER_ADD" "$SERVER_PORT" )
    
echo "$result"

这是可行的,除了 sleep 必须比服务器可能响应的最长时间更长。这意味着每次调用都会花费那么长的时间,这将最短时间从几十毫秒推到几十秒。我需要我的脚本等待第一行响应,然后终止进程,以便它可以继续做其他事情。

(是的:我知道显而易见的答案是“使用 expect”。不幸的是,我的目标是嵌入式系统,并添加了 expect 和它编写的 TcL 脚本引擎in 会使我的图像大小增加大约一兆字节。不可以。)

经过反复试验,我得出了以下结论:

#!/bin/sh

SERVER_ADD=localhost
SERVER_PORT=9995

result=$( ( echo '{"op":"get","path":"access"}'; sleep 30 ) |
    telnet "$SERVER_ADD" "$SERVER_PORT" |
    while read -r line; do
        echo "$line"
        killall sleep
    done ) 2>/dev/null
echo "$result"

解释

  • 设置一个子 shell 来回显查询,然后休眠足够长的时间以获得最长的响应时间
  • 通过管道连接到 telnet 以建立连接
  • 将服务器响应管道化为一个循环,一次一行
  • 捕获并回显第一行后,按名称终止 sleep 命令,这将结束子 shell,从而结束 telnet 连接
  • 2>/dev/null 使用 sleep 命令在终止时打印的“Terminated”消息

除了 killall sleep 之外,这很好用。这将杀死该用户控制下的每个 sleep 实例。大多数时候这不会成为问题,但其他时候这将是一个严重令人困惑的错误来源。

我怎样才能在需要时杀死那个 sleep(或整个子 shell),而不会造成附带损害?

最佳答案

您可以尝试使用 fifo 将数据发送到 telnet,这样您就可以在需要的时候关闭它。

rm -f myfifo
mkfifo myfifo
result=$(
    telnet "$SERVER_ADD" "$SERVER_PORT"  <myfifo  |
    (  echo '{"op":"get","path":"access"}'  >&5
       while read -r line; do
          echo "$line"
          exec 5>&-
       done
    ) 5>myfifo
)

语法 5>myfifo(无空格)打开一个新的输出文件描述编号 5 写入 fifo。 echo >&5 写入此 fd。 exec 5>&- 关闭这个 fd。此语法应适用于 ash

关于shell - 从管道的后面杀死管道中的特定进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67349412/

相关文章:

c - 测量进程的生命周期(因为它被加载到内存中)

python - Telnet 自动化/脚本

python行编辑telnet服务器

regex - sed - 在模式中包含换行符

linux - 打开/关闭环境变量

linux - 子进程互相等待

java - Java 控制台上的 Telnet 连接

linux - 如何将后台程序调到前台

linux - 剪切删除我文件的所有内容

c - 子进程不读取 PIPE