【问题标题】:shell script gives incorrect output when invoked using Ansible shell module使用 Ansible shell 模块调用时,shell 脚本给出不正确的输出
【发布时间】:2020-01-07 00:55:44
【问题描述】:

我有希望在目标节点上运行的 check.sh 脚本:

cat check.sh

str=`echo $1 | sed -e 's#[\][\]n# #g'`
echo $str>check.row

假设用参数中的单个空格替换 \n 并将其保存在 check.row 文件中。

当我在目标服务器上手动运行它时,我得到了如下所示的良好输出结果:

bash -x ./check.sh '/fin/app/01/scripts\\n/fin/app/01/sql'
++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'
++ sed -e 's#[\][\]n# #g'
+ str='/fin/app/01/scripts /fin/app/01/sql'
+ echo /fin/app/01/scripts /fin/app/01/sql

生成的check.row如下所示:

[user1@remotehost1 ~]$ cat check.row 
/fin/app/01/scripts /fin/app/01/sql

但是,当我使用 ansible shell 或命令模块运行相同的命令时,我没有得到预期的结果。

下面是我的剧本:

  tasks:
   - copy:
       src: "{{ playbook_dir }}/files/check.sh"
       dest: "~/"
       mode: 0754

   - set_fact:
       install_dir: "{{ hostvars[\'localhost\'][\'command_result\'].stdout.split('\t')[2] }}"

   - shell: "bash -x  ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"

查看 ansible 的调试输出如下:

changed: [10.8.44.55] => {
    "changed": true, 
    "cmd": "bash -x  ~/check.sh '/fin/app/01/scripts\\n/fin/app/01/sql' > ~/check_rollback.log", 
    "delta": "0:00:00.118943", 
    "end": "2019-09-04 10:50:16.503745", 
    "invocation": {
        "module_args": {
            "_raw_params": "bash -x  ~/check.sh '/fin/app/01/scripts\\n/fin/app/01/sql' > ~/check_rollback.log", 
            "_uses_shell": true, 
            "argv": null, 
            "chdir": null, 
            "creates": null, 
            "executable": null, 
            "removes": null, 
            "stdin": null, 
            "stdin_add_newline": true, 
            "strip_empty_ends": true, 
            "warn": true
        }
    }, 
    "rc": 0, 
    "start": "2019-09-04 10:50:16.384802", 
    "stderr": "++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'\n++ sed -e 's#[\\][\\]n# #g'\n+ str='/fin/app/01/scripts\\n/fin/app/01/sql'\n+ echo '/fin/app/01/scripts\\n/fin/app/01/sql'", 
    "stderr_lines": [
        "++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'", 
        "++ sed -e 's#[\\][\\]n# #g'", 
        "+ str='/fin/app/01/scripts\\n/fin/app/01/sql'", 
        "+ echo '/fin/app/01/scripts\\n/fin/app/01/sql'"
    ], 
    "stdout": "", 
    "stdout_lines": [] }

这里是 ansible 运行的 check.row 文件输出:

[user1@remotehost1 ~]$ cat check.row 
/fin/app/01/scripts\\n/fin/app/01/sql

现在打印的是 \n,而不是单个空格。

我正在使用最新版本的 ansible。

可以轻松复制此问题。您能否建议我为什么会遇到此问题以及如何解决此问题?

【问题讨论】:

  • hexdump -C <<<"$1" >>check.row 添加到您的脚本中,看看$1 的真正内容。记得引用你的论点,不是echo $1,而是echo "$1"etc。
  • @Ashar,你的问题解决了吗?
  • 我需要在周末测试一下。问题可能是使用 printf vs echo。肯定有很多解决方案可以替换字符串并在 shell 脚本上完成这项工作,但是当通过 Ansible 调用时同样失败。可能是一个全新的帖子,我会在其中介绍所有案例。

标签: shell ansible format


【解决方案1】:

首先,您使用的shell模块中只指定了shell命令,您在其中错误地使用了bash。

shell: "bash -x  ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"

其次,如您所见,您的任务导致了附加输出中的错误。

Stdout 为空,我们可以在 stderr 中看到错误。

第三,如果你想使用bash可以使用命令模块,如下图,

- command: "bash -x  ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"

我还建议在您的 check.sh 脚本中进行以下更改,

#!/bin/bash
echo $1 # You can check the value that is passed to the script
str=$(echo "$1" | sed -e 's/\\n/ /g') # Use quotes around your variable
echo "$str" > check.row

而且运行良好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    相关资源
    最近更新 更多