【问题标题】:Why is the output of this bash script different every time it is run?为什么这个 bash 脚本每次运行的输出都不一样?
【发布时间】:2016-08-10 21:42:53
【问题描述】:

我有以下简短的 bash 脚本:

#!/bin/bash
cp /dev/null out.sh
while IFS=' ' read -r b c d e
do
    echo -ne "sendevent " >> out.sh
    echo -ne "/dev/input/event1 " >> out.sh
    echo -ne "$(( 0x$c )) " >> out.sh
    echo -ne "$(( 0x$d )) " >> out.sh
    echo -ne "$(( 0x$e )) " >> out.sh
    echo >> out.sh
done < "in.sh"

它以/dev/input/event1: 0003 0039 0000006d 的形式接收从另一个名为in.sh 的脚本中读取的命令,我需要它以sendevent /dev/input/event1 3 57 109 的形式输出到另一个名为out.sh 的脚本中,并在其中转换后三个从十六进制到十进制的术语。

但是,当我运行脚本时,我得到一个准损坏的输出,每次运行它都会改变。正确的输出应该是:

sendevent /dev/input/event1 3 57 109
sendevent /dev/input/event1 3 53 40
sendevent /dev/input/event1 3 54 620
#and so on

这是我实际输出的图片:

每次我运行脚本时,输出都会略有不同,而且永远不会像我想要的那样统一。为什么每次输出都不一样?如何修复它,使其以我想要的形式输出?

我尝试在最后一个echo 语句之后添加sleep .01,但并没有解决问题。

编辑:根据要求,这是我的in.sh的sn-p:

/dev/input/event1: 0003 0039 0000006d
/dev/input/event1: 0003 0035 00000028
/dev/input/event1: 0003 0036 0000026c
/dev/input/event1: 0001 014a 00000001
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0039 ffffffff
/dev/input/event1: 0001 014a 00000000
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0039 0000006e
/dev/input/event1: 0003 0035 0000020f
/dev/input/event1: 0003 0036 000003dd
/dev/input/event1: 0001 014a 00000001
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0039 ffffffff
/dev/input/event1: 0001 014a 00000000
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0039 0000006f
/dev/input/event1: 0003 0035 000001b6
/dev/input/event1: 0003 0036 00000076
/dev/input/event1: 0001 014a 00000001
/dev/input/event1: 0000 0000 00000000
/dev/input/event1: 0003 0039 ffffffff

这里有两个不同的输出,一个接一个地运行,使用相同的in.sh

sendevent /dev/input/event1 3 109
sendevent /dev/input/event1 3 54 620
sendevent /dev/input/event1 1 330 1
sendevent /dev/input/event1 0 0 0
sendevent /dev/input/event1 3 57 4294967295
/dev/input/event1 1 330 0
sendevent /dev/input/event1 0 0
sendevent /dev/input/event1 3 57 110
3 53 527
sendevent /dev/inp3 54 989
/dev/input/event1 1 330 1
sendevent 3 57 4294967295
sendevent /dev/input/event1 /event1 1 330 0
sendevent /dev/input/event1 0 0 0
sendevent /dev/input/event1 57 111
sendevent /dev/input/event1 3 53 438 sendevent /dev/input/event1 3 54
sendevent /dev/input/event1 1 1
sendevent
sendevent /dev/input/event1 57 4294967295
/dev/input/event1 1 330 /dev/input/event1 0 0 0
sendevent /dev/input/event1 3 57 112
sendevent /dev/input/event1 3 53
sendevent /dev/input/event1 3 54 881
sendevent /dev/input/event1
sendevent /dev/input/event1 3 57 t1 0 0 0 4294967295
sendevent 1 330 0
sendevent/dev/input/event1 0 0 0
113
sendevent /dev/input/event1 3 53
sendevent /dev/input/event1 54 901
/dev/input/event1 1 330 1
/dev/input/event1 0 0 0 sendevent /dev/input/event1 3 57 4294967295
330 0

第二个输出:

sendevent /dev/input/event1 3 57 109
sendevent /dev/input/event1 3 53 620
sendevent /dev/input/event1  54 1 330 1 /dev/input/event1 0 0 0 sendevent /dev/input/event1 3 57 
sendevent /dev/input/event1 1 330
sendevent /dev/input/event1 0 0 0
sendevent /dev/input/event1 3 57 110
/dev/input/event1 3 53
sendevent /dev/input/event1 54 989
/dev/input/event1 1 330
sendevent /dev/input/event1 0 0
sendevent 3 57 4294967295
 sendevent /dev/input/event1 1 0
sendevent 0 0 0
put/event1 sendevent /dev/input/event1 3 111
sendevent 3 53 438
/event1 sendevent /dev/input/event1 3 54
sendevent /dev/input/event1 330 1
0 0 0
nt /dev/input/event1 sendevent /dev/input/event1 3 4294967295
sendevent 0
sendevent /dev/input/event1 0 0 0
sendevent /dev/input/event1 3 57 112
sendevent /dev/input/event1 3 53 247
sendevent /dev/input/event1 3 54 881 sendevent /dev/input/event1 1 330 1
/dev/input/event1 0 0
sendevent /dev/input/event1 57 4294967295
sendevent /dev/input/event1 1 330
sendevent /dev/input/event1 0 0 0
sendevent 3 57 113
sendevent 3 53 246
/event1 sendevent /dev/input/event1 3 54
sendevent /dev/input/event1 330 1
/dev/input/event1 0 0 0
/dev/input/event1 3 57 4294967295 sendevent /dev/input/event1 1 330
sendevent /dev/input/event1 0 0
sendevent 3 57 114
/event1 sendevent /dev/input/event1 3 53
sendevent /dev/input/event1 3 54 882 sendevent /dev/input/event1 1 1
sendevent /dev/input/event1 0 0 0 sendevent /dev/input/event1 3 sendevent /dev/input/event1 1 0
sendevent 0 0 0

【问题讨论】:

  • 仅供参考,echo -ne 的 POSIX 指定替代方案是 printf '%b'
  • 您是要阅读 脚本 in.sh 还是 in.sh 的输出?因为您的脚本当前正在读取脚本文件的内容。
  • ...也就是说,您应该永远在不使用 shell 自身转义功能的情况下通过字符串连接生成代码(即printf '%q');沿着这条路存在外壳注入漏洞。
  • 图片实际上是有问题的,因为试图重现问题的人无法复制和粘贴它们。提供文本要好得多(如果您已经测试过将您的确切代码和您的确切文本结合起来产生您的确切输出,那就更好了)。
  • 嗯。我无法重现该问题——使用您的原始代码和您发布的输入,每次运行我都会得到完全相同的输出。可能需要调查执行环境以弄清楚到底发生了什么。

标签: shell echo sh


【解决方案1】:

下面使用初始 grep 传递来清理输入,避免潜在的 shell 注入攻击:

#!/bin/sh
grep '^[^ ]\+ [0-9a-f ]\+$' <in.sh | while IFS=' ' read -r _ c d e; do
  printf 'sendevent /dev/input/event1 %d %d %d\n' \
    "$(( 0x$c ))" "$(( 0x$d ))" "$(( 0x$e ))" 
done >out.sh

注意:

  • out.sh 仅打开一次,而不是在每个要写入它的命令之前重新打开,并在该单个命令结束后关闭(就像每次写入时使用 &gt;&gt; 运算符一样)。
  • 每行使用一次printf 可确保每次写入都以原子系统调用的形式发生(当使用足够短的行时,就像这里可靠的情况一样),并且还避免依赖于the POSIX specification for echo explicitly declines to specify 的行为; echo -n 的输出在标准中明确未定义,而将 -e 视为选项而不是参数实际上与标准的字母相反(并且 bash 的默认行为可以关闭,就像结合set -o posixshopt -s xpg_echo)。

【讨论】:

  • 哇,我试图给你一个in.shout.sh 的例子,但你的回答已经解决了我的问题。您还希望我提供其他代码示例,以供将来参考吗?感谢您真的快速回答
  • 如果你能得到一个合适的独立复制器,让其他人可以自己运行来查看问题,那么在帮助问题对其他人有用方面会有很大帮助人——所以如果你不介意继续努力,请做!
最近更新 更多