简体   繁体   中英

shell script gives incorrect output when invoked using Ansible shell module

I have check.sh script that I wish to run on the target nodes:

cat check.sh

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

It is suppose to replace \\n with a single white space from the argument and save it in check.row file.

When I run it manually on the target server i get good output results as shown below:

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

The check.row generated looks good as below:

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

However, when i run the same using ansible shell or command module I do not get the expected results.

Below is my playbook:

  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"

See ansible's debug output below:

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": [] }

And here is the check.row file output from ansible's run:

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

As you can instead of single whitespace it is now printing \\n.

I am on the latest version of ansible.

One can replicate this issue easily. Can you please suggest why am I getting this issue and how to fix this?

First of all, you are using the shell module in which only the shell command is specified, you have incorrectly used bash in it.

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

Secondly, as you can see your task has resulted in an error as seen in your attached output.

Stdout is empty and we can see an error in stderr.

Thirdly, If you want to use bash you can use command module, as shown below,

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

I also suggest the following changes in your check.sh script,

#!/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

And it is working fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM