【发布时间】:2021-07-24 17:06:49
【问题描述】:
我正在编写一个 shell 脚本,它使用 telnet 连接到服务器,发送查询,然后获取单行响应以进行进一步处理。经典的解决方案是设置一个子shell,其中echos 查询然后运行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 脚本引擎会增加一个兆字节到我的图像大小。不行。)
经过多次尝试和错误,我想出了以下内容:
#!/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命令在终止时打印的“已终止”消息
这很好用,除了killall sleep。这将在此用户的控制下杀死 sleep 的每个实例。大多数情况下这不会是一个问题,但其他时候它会是一个严重令人困惑的错误来源。
我怎样才能在需要时杀死sleep(或整个子shell)而不造成附带损害?
【问题讨论】: