Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to escape special characters in ansible shell module

Tags:

bash

yaml

ansible

I tried bash escape and double quotes methods to escape the special characters in below shell command, But both didn't work, What is the proper way to escape special characters in ansible playbook?

 The offending line appears to be:

                 name: Syncing system date with htpdate failed!, Trying wget method...
                 shell: date -s "$(curl -s --head http://google.com | grep '^Date:' | sed 's/Date: //g' ) +0530"
                                                                                                ^ here

    exception type: <class 'yaml.scanner.ScannerError'>
    exception: mapping values are not allowed in this context
      in "<unicode string>", line 15, column 93
like image 494
Shyam Jos Avatar asked Feb 14 '18 12:02

Shyam Jos


People also ask

How do you escape the special characters in Ansible?

Yes, you need to escape '$' sign with '\', and it's executed in the server, it just won't show in the resulting output. Because in some cases like 'awk' with 'print' not working with Ansible ad-hoc command and need to utilize playbooks. It will spit out the result you want.

How do you escape special characters in shell?

The escape (\) preceding a character tells the shell to interpret that character literally. With certain commands and utilities, such as echo and sed, escaping a character may have the opposite effect - it can toggle on a special meaning for that character.

How do you escape special characters in Bash?

3.1. 2.1 Escape CharacterA non-quoted backslash ' \ ' is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline .

How do you escape single quotes in Ansible?

In '\'' first ' closes string, then \' glues escaped single quote, then ' starts next string to be glued.

How to use Bash special characters in Ansible shell commands?

One of the hurdles is if you want to use any of bash special characters like @ or ! in your shell command, or, if you want to double escaping it from the original shell command. If you can escape all charater in the remote server environment without using single quote, then you can also with Ansible ‘shell’ module.

How to escape command in Ansible with single quote?

You can use single quote also, but in any condition you can’t use it like when you need to use command with its own single quote to escape (making it double escape with ansible command), it’s preferrably to escape plainly using ‘’ first, like this example (escaping dot): # ansible server -m shell -a “ls -al| grep config.new”

How does the ansible shell module work?

The shell module takes the command name followed by a list of space-delimited arguments. Either a free form command or cmd parameter is required, see the examples. It is almost exactly like the ansible.builtin.command module but runs the command through a shell ( /bin/sh) on the remote node.

How do I use variables in Ansible script?

To use a variable and realized properly, use { { var|quote }} rather than just { { var }}. This will make sure no special characters like semicolon will be realized. When you need to run a script, then use the Ansible script module with a template module, if required.


1 Answers

One of the problems here is the colon followed by a space :. This is usually an indicator for a mapping key.

YAML does not allow nested mappings on one line, e.g.:

foo: bar: baz

That's why YAML designers chose to forbid : in a mapping value if it's on the same line as the key. (It could have been been solved as well by simply ignoring further occurances and treat that as regular content.)

You have several choices. You can just put the whole value in quotes, which is not a good idea in this case since you have both single and double quotes which you would have to escape then.

A workaround can be to escape the space in the sed command:

shell: date -s "$(curl -s --head http://google.com | grep '^Date:' | sed 's/Date:\ //g') +0530"

A more general solution is to use a folded block scalar:

shell: >
  date -s "$(curl -s --head http://google.com | grep '^Date:' | sed 's/Date: //g') +0530"

You could even seperate this into several lines now, because the folded block scalar will fold consecutive lines into one:

shell: >
  date -s "$(curl -s --head http://google.com
  | grep '^Date:' | sed 's/Date: //g') +0530"

The second problem is, as Javier mentioned, the sed expression s/Date/: //g. You probably want s/Date: //g. Also look at the suggestion by @tripleee how to improve your command.

like image 57
tinita Avatar answered Oct 13 '22 20:10

tinita