为什么 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 command
或 shell
模块执行相同的脚本时,无论我指定 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]
有人知道为什么 shell
和 command
模块会产生这个错误吗?
有关脚本失败的远程主机的更多信息:
- SunOS 5.10 Generic_150401-18 i86pc i386 i86pc
- 所有 shells (
/bin/sh
, /bin/bash
, /bin/ksh
) 都是 GNU bash, 版本 4.1.2(1)-release (x86_64-redhat-linux-gnu)
- Python 2.6.6
语言环境不同!当我登录或执行远程 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 扩展的字符范围规范 。如果碰巧你有一个名为 :
、u
、p
、e
、r
、l
、o
的文件,或 w
这将在 tr
将其视为参数之前展开:
$ touch u
$ echo [:upper:]
u
修复:使用引号,如
tr '[:upper:]' '[:lower:]'
好的。因此,不管 Jens 怎么说,该脚本在大多数环境中都不是 "broken"。我按照 bash
、bash --posix
、dash
、busybox sh
和 ksh
包中的 bash
、bash --posix
、dash
、ksh
进行了测试,在所有情况下它有效。
所以我开始搜索特定的错误消息 (Bad string
),并找到:
http://sourceforge.net/p/wrapper/bugs/229/
这似乎准确地描述了您的问题。这不是脚本中的错误;这是 Solaris 上 tr
中的一个错误。
我在 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 command
或 shell
模块执行相同的脚本时,无论我指定 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]
有人知道为什么 shell
和 command
模块会产生这个错误吗?
有关脚本失败的远程主机的更多信息:
- SunOS 5.10 Generic_150401-18 i86pc i386 i86pc
- 所有 shells (
/bin/sh
,/bin/bash
,/bin/ksh
) 都是 GNU bash, 版本 4.1.2(1)-release (x86_64-redhat-linux-gnu) - Python 2.6.6
语言环境不同!当我登录或执行远程 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 扩展的字符范围规范 。如果碰巧你有一个名为 :
、u
、p
、e
、r
、l
、o
的文件,或 w
这将在 tr
将其视为参数之前展开:
$ touch u
$ echo [:upper:]
u
修复:使用引号,如
tr '[:upper:]' '[:lower:]'
好的。因此,不管 Jens 怎么说,该脚本在大多数环境中都不是 "broken"。我按照 bash
、bash --posix
、dash
、busybox sh
和 ksh
包中的 bash
、bash --posix
、dash
、ksh
进行了测试,在所有情况下它有效。
所以我开始搜索特定的错误消息 (Bad string
),并找到:
http://sourceforge.net/p/wrapper/bugs/229/
这似乎准确地描述了您的问题。这不是脚本中的错误;这是 Solaris 上 tr
中的一个错误。