1

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?

3
  • Add hexdump -C <<<"$1" >>check.row to your script and see what's really inside $1. Remember to quote your arguments, no echo $1 but echo "$1"etc. Commented Sep 4, 2019 at 7:21
  • @Ashar, Is your issue fixed? Commented Sep 5, 2019 at 18:54
  • I need to test around this on weekend. The issue could be use of printf vs echo. There is definately many solutions that replace the strings and do the job on shell script however the same fails when invoked through Ansible. May be a new post altogether where I present all cases. Commented Sep 6, 2019 at 4:31

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.