【问题标题】:Why does Ansible fail to execute this simple shell script?为什么 Ansible 无法执行这个简单的 shell 脚本?
【发布时间】:2015-02-13 21:34:01
【问题描述】:

我在 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,我都会收到“错误字符串”错误:

- 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 模块会产生这个错误吗?

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

  • SunOS 5.10 Generic_150401-18 i86pc i386 i86pc
  • 所有 shell(/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 的参数不是一个选项,该脚本是软件包安装的一部分,我无法修改该代码。
  • @dokaspar 那么是时候向编写该损坏脚本的人报告错误了。
  • @Jens:是的,我一定会这样做的!
  • 您能否将 tr 脚本替换为另一个脚本,忽略参数而只执行 tr '[:upper:]' '[:lower:]'。或者当您不想更改 tr 时,在执行包安装之前更改您的 PATH?

标签: string bash shell solaris ansible


【解决方案1】:

好的。因此,不管 Jens 怎么说,该脚本在大多数环境中都没有“损坏”。我在pdksh 包中的bashbash --posixdashbusybox shksh 下对其进行了测试,并且在所有情况下它都有效。

所以我去搜索那个特定的错误消息(Bad string),发现:

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

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

【讨论】:

  • 脚本 损坏:[:upper:][:lower:] 必须引用! 那是因为 [...] 将被理解shell 作为一个字符范围。从包含例如名为u 的文件的文件夹中尝试它。您会看到(未引用)[:upper:] 将扩展为 u。这并不是因为它似乎在大多数时候都在工作,它确实每次都工作。 @Jens 在他的回答中很好地解释了这一点。
  • 是的,我对引用的评论来自于在 Solaris 上找到有关“损坏”/bin/tr 的类似信息。
  • 脚本坏了,再多的挥手也改变不了它。如果脚本的 CWD 中有一个名为 u 的单字符文件,则 tr 正在将 u 转换为 u,实际上什么都不做。如果有 两个 一个字符文件,例如 er,它将运行 tr e r e r,但会失败并出现错误。这可能不是你的错误,而是一颗等待爆炸的定时炸弹。
  • 无论如何,引用不是错误背后的问题。如果遇到错误的shell扩展引起的问题,也许OP可以打开一个新问题。
  • 我开始觉得两者都是真的...... (1) 脚本 坏了,因为它在 CWD 中有一个名为 u 的文件失败,并且(2) Solaris tr 中也存在一个bug,因为脚本在任何其他环境下仍然有效(前提是没有文件名为u...)
【解决方案2】:

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

tr [:upper:] [:lower:]

因为[] 是一个字符范围规范由外壳扩展。如果你有一个名为:uperlow 的文件,它将在tr 看到之前扩展作为论据:

$ touch u
$ echo [:upper:]
u

修正:使用引号,如

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

【讨论】:

  • 谁是这两个被误导的人否决了这个答案?甚至没有提供理由?
  • +1 感谢您的解释!不幸的是,未引用的参数位于我无法自行修复的代码中:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-29
  • 2012-03-29
相关资源
最近更新 更多