设置超时变量输出

设置超时变量输出

我正在尝试通过 telnet 自动查询状态(在这种情况下我无法解决此问题)。这个想法是 grep 查找某些内容并将结果分配给一个变量,以便稍后传递给条件语句。复杂的是到目标设备的链接可能未启动,因此如果不通过超时终止脚本可能会无限期挂起。

这设置output为我所期望的,但不处理链接关闭:

output=$(telnet 1.2.3.4 1234 | grep "something")

这将在处理链接关闭时输出预期的输出:

timeout --signal=9 3 telnet 1.2.3.4 1234 | grep "something"

我什至可以将输出定向到一个文件,该文件将包含输出:

timeout --signal=9 3 telnet 1.2.3.4 1234 | grep "something" > /tmp/tmpfile.txt

不幸的是,像这样的文件的快速写入/读取不是一个选项,因为它会填满日志文件。

但是,当我尝试组合所有内容时,变量没有设置:

output=$(timeout --signal=9 3 telnet 1.2.3.4 1234 | grep "something")

或者更确切地说,它将其设置为空白值,因为如果我在运行上面之前设置它,则该变量之后将为空。

答案1

telnet期望其标准输入上有 tty,但timeout将其删除。

如果您确实坚持使用 telnet,您可以通过--foreground向 中添加选项来实现timeout,如下所示:

output=$(timeout --foreground --signal=9 3 telnet 1.2.3.4 1234 2>&1 | grep "something")

此外,如果您nc的系统上可以安装它,您真的应该将其用于您的目的:

output=$(timeout 3 nc 1.2.3.4 1234 | grep "something")

如果两者都不nc适合timeout --foreground您,那么您确实需要一种不需要 tty 的 telnet 替代方案。

我看到你标记了你的问题bash,所以你可以使用 Bash 自己的网络设施,因此你的行可能会变成这样:

output=$(timeout 3 cat < /dev/tcp/1.2.3.4/1234 | grep "something")

如果甚至都不cat是一个选项,那么您可以将其替换为 Bash 中的单行脚本,如下所示:

output=$(timeout 3 stdbuf -oL bash -c 'while read line ; do echo "${line}" ; done < /dev/tcp/1.2.3.4/1234 | grep "something"')

希望至少stdbuf(它是标准 coreutils 包的一部分)在您的系统中可用。

然而,在最后一个替代方案中,请注意您的 grep 正则表达式:如果其中有单引号,那么您需要首先退出主要单引号对来转义它们。

如果您需要将变量(例如主机名和/或端口号)从 shell 传递到单行脚本,那么也需要这样做。例如:

hostname=1.2.3.4
portnumber=1234

output=$(timeout 3 stdbuf -oL bash -c 'while read line ; do echo "${line}" ; done < /dev/tcp/'"${hostname}"'/'"${portnumber}"' | grep "something"')

在这里,我假设${hostname}${portnumber}是可以信任的,即由您或其他可信来源提供,不会提供非法、无效或危险的值。

答案2

这是未重定向的标准错误(当您的链接断开时)!这将解决您的问题,因为它将标准错误重定向到标准输出。

output=$(timeout --signal=9 3 telnet 1.2.3.4 1234 2>&1 | grep "something") 

相关内容