为什么 Ansible 无法执行这个简单的 shell 脚本?

Why does Ansible fail to execute this simple shell script?

我在 Ansible (1.8.2) 中遇到了一个非常奇怪的问题,归结为在 shell 脚本中执行这个简单的命令:

#!/bin/sh

# transform a String into lowercase chars:
echo "TeSt" | tr [:upper:] [:lower:]

当我登录到远程 Solaris 机器时,无论我在 shell 哪个位置(例如 /bin/sh/bin/bash),这个脚本似乎都有效:

# ./test.sh 
test

另外,当我使用远程 ssh 命令执行此脚本时,它有效:

# ssh root@<remote-host> '/tmp/test.sh'
test

但是,当我使用 Ansible commandshell 模块执行相同的脚本时,无论我指定 shell 什么,我都会收到 "Bad String" 错误:

- shell: executable=/bin/sh /tmp/test.sh      [FATAL stderr: Bad string]
- shell: executable=/bin/bash /tmp/test.sh    [FATAL stderr: Bad string]
- command: /tmp/test.sh                       [FATAL stderr: Bad string]

我花了很长时间才弄清楚它与 raw 模块一起工作:

- raw: executable=/bin/sh /tmp/test.sh        [OK]

有人知道为什么 shellcommand 模块会产生这个错误吗?

有关脚本失败的远程主机的更多信息:

语言环境不同!当我登录或执行远程 ssh 命令时,语言环境如下所示:

LANG=
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_ALL=

然而,使用 Ansible,我得到了这个:

LANG=en_US.UTF-8
LC_CTYPE=en_US.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_ALL=

无论您有什么其他问题,您的 tr 命令肯定有问题,

tr [:upper:] [:lower:]

因为 [] 是由 shell 扩展的字符范围规范 。如果碰巧你有一个名为 :uperlo 的文件,或 w 这将在 tr 将其视为参数之前展开:

$ touch u
$ echo [:upper:]
u

修复:使用引号,如

tr '[:upper:]' '[:lower:]'

好的。因此,不管 Jens 怎么说,该脚本在大多数环境中都不是 "broken"。我按照 bashbash --posixdashbusybox shksh 包中的 bashbash --posixdashksh 进行了测试,在所有情况下它有效。

所以我开始搜索特定的错误消息 (Bad string),并找到:

http://sourceforge.net/p/wrapper/bugs/229/

这似乎准确地描述了您的问题。这不是脚本中的错误;这是 Solaris 上 tr 中的一个错误。