shell 将'echo'的输出通过管道传送到netcat失败,而'printf'的输出通过管道传送

ht4b089n  于 2022-11-16  发布在  Shell
关注(0)|答案(2)|浏览(116)

我在Linux Ubuntu 18.04和20.04上使用netcatnc)通过TCP以太网向Teledyne LeCroy T3PS3000电源设备发送命令。如果我使用echo,设备无法正确接收命令,但如果我使用printf,它可以正常工作。为什么?

# Example command to Ethernet-connected digital power supply over TCP

# fails
echo 'measure:voltage? ch1' | timeout 0.2 nc 192.168.0.1 5025

# works
printf 'measure:voltage? ch1' | timeout 0.2 nc 192.168.0.1 5025

参考文献:

  1. timeout指令:https://unix.stackexchange.com/questions/492766/usage-of-nc-with-timeouts-in-ms/492796#492796
    1.更新/备注(在我写下答案后书写,因此下面的printf表格是正确的):如果没有timeout命令,我们将不得不使用-w选项和netcat,但它只接受整数等待周期超时(以秒为单位),如下所示(注意-w 1将'w'等待周期或超时设置为1整秒):
printf '%s' "my command to send" | nc -w1 192.168.0.1 5025

*Teledyne LeCroy T3PS3000电源:从我的eRCaGuy_dotfiles存储库中的git & Linux cmds, help, tips & tricks - Gabriel.txt文档:

1.如需帮助,请联系:
Teledyne LeCroy支持
support@teledynelecroy.com
切斯特纳特岭路700号
切斯特纳特岭,纽约州10977
(800)553-2769备选案文3
1.手册上没有,所以我发邮件给他们,他们告诉我:
T3 PS3000使用套接字通信,默认端口为5025。

hgncfbus

hgncfbus1#

找到了。

确保您没有在命令末尾意外发送换行符(\n

看起来像是echo在字符串后面添加了一个换行符,而printf没有,这个换行符干扰了设备解析命令的能力。如果我强行将它(一个换行符,\n)添加到printf cmd的末尾,那么它也会失败--这意味着设备不会像预期的那样响应命令:

# fails:
printf 'measure:voltage? ch1\n' | timeout 0.2 nc 192.168.0.1 9999

...看起来您可以使用-n来隐藏echo的结尾换行符:

# works!
echo -n 'measure:voltage? ch1' | timeout 0.2 nc 192.168.0.1 9999

# also works, of course, as stated in the question
printf 'measure:voltage? ch1' | timeout 0.2 nc 192.168.0.1 9999

man echo开始:

-n     do not output the trailing newline

要点:请使用printfecho -n,以避免在打印文件的末尾出现尾随换行符。
但是,这还不是结束!这里还有两点:

1.如果您希望获得可移植的预期行为,以及向设备发送 * 任何 * 命令的能力,请不要在任何shell脚本中 * 使用echo *!

当试图用echo * 向设备发送任何可能的字符串时,使用echo * 实际上是一个坏主意!为什么?嗯,@Jeff Schaller在评论中向我指出了以下资源,它有 * 吨 * 真正有价值的信息:Unix和Linux:为什么printf比echo好?

不使用echo的几个主要原因包括:

1.它的实现、参数和行为都有一点笨拙。
1.它是不可移植的:它有各种各样的实现,在不同的系统中有很大的不同。有些支持-e-n,有些不支持。有些默认情况下具有-e行为,但没有-e。等等。
1.它不能将-n作为命令输出,在某些shell上 * 完全 *。请在这里查看我的评论。
在Ubuntu 18.04和20.04上的bash中,echo "-n"应该输出-n,但是它什么也不输出,因为它接受-n-n标志的相同内容。echo -- "-n"应该解决这个问题并输出-n,但它没有。它输出的是-- -n。我现在很明白你的意思了。printf更好。
1.正如@查尔斯·达菲在评论中指出的:即使是the POSIX specification for echo也建议不要使用echo,因为存在以下许多不一致之处和原因:
不可能在所有POSIX系统上使用echo...
鼓励新应用程序使用printf而不是echo
仅供参考,以下是Unix和Linux的几句关键名言:为什么printf比echo更好?:
关于echo
...请确保$var不包含反斜杠字符,并且不以-开头
关于printf
但要记住第一个参数是格式,所以不应该包含变量/不受控制的数据。

2.将printf * 正确 * 用作printf '%s' "my command string",而不是printf "my command string"

在下面的评论中看到更多的讨论,在我和@查尔斯·达菲之间。你应该像这样使用printf

# CORRECT USAGE: >>> FINAL ANSWER; DO THIS! <<<
printf '%s' 'measure:voltage? ch1' | timeout 0.2 nc 192.168.0.1 9999  

# NOT this:
printf 'measure:voltage? ch1' | timeout 0.2 nc 192.168.0.1 9999

这是因为传递给printf的第一个参数被解析为 * 格式字符串 *。例如,如果您试图发送给设备的命令字符串是%s,则它不会发送任何内容!:

printf "%s"

输出为空,因为printf将第一个参数解释为格式字符串,而%s表示格式字符串中的一些特殊内容。

printf "%s" "%s"

输出为

%s

根据printf规范,printf的参数中的第一个"%s"是 * 格式字符串 *,第二个"s"是要替换到第一个%s所在的格式字符串中的 * 字符串文字 *。

这意味着正确使用printf将能够向设备发送ANY命令,而错误使用将删除任何格式字符,如%s%02X%u等--任何printf -style format string special chars or sequences

另请参阅:

  1. Unix和Linux:为什么printf比echo好?
  2. the POSIX specification for echo
i2byvkas

i2byvkas2#

看来Ubuntu 18.04上的netcat改了,你可以用“netcat-N”来完成交易。

相关问题