How to do multiline shell script in Ansible
ShellAnsibleShell Problem Overview
right now I am using a shell script in ansible that would be much more readable if it was on multiple lines
- name: iterate user groups
shell: groupmod -o -g {{ item['guid'] }} {{ item['username'] }} ....more stuff to do
with_items: "{{ users }}"
Just not sure how to allow multiline script in Ansible shell module
Shell Solutions
Solution 1 - Shell
Ansible uses YAML syntax in its playbooks. YAML has a number of block operators:
-
The
>
is a folding block operator. That is, it joins multiple lines together by spaces. The following syntax:key: > This text has multiple lines
Would assign the value
This text has multiple lines\n
tokey
. -
The
|
character is a literal block operator. This is probably what you want for multi-line shell scripts. The following syntax:key: | This text has multiple lines
Would assign the value
This text\nhas multiple\nlines\n
tokey
.
You can use this for multiline shell scripts like this:
- name: iterate user groups
shell: |
groupmod -o -g {{ item['guid'] }} {{ item['username'] }}
do_some_stuff_here
and_some_other_stuff
with_items: "{{ users }}"
There is one caveat: Ansible does some janky manipulation of arguments to the shell
command, so while the above will generally work as expected, the following won't:
- shell: |
cat <<EOF
This is a test.
EOF
Ansible will actually render that text with leading spaces, which means the shell will never find the string EOF
at the beginning of a line. You can avoid Ansible's unhelpful heuristics by using the cmd
parameter like this:
- shell:
cmd: |
cat <<EOF
This is a test.
EOF
Solution 2 - Shell
Tried with ansible 2.0.0.2:
---
- hosts: all
tasks:
- name: multiline shell command
shell: >
ls --color
/home
register: stdout
- name: debug output
debug: msg={{ stdout }}
The shell command is collapsed into a single line, as in ls --color /home
Reference (visited in 2021): https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html ==> search form "multiple lines" in the page.
Solution 3 - Shell
Adding a space before the EOF delimiter allows to avoid cmd:
- shell: |
cat <<' EOF'
This is a test.
EOF
Solution 4 - Shell
I prefer this syntax as it allows to set configuration parameters for the shell:
---
- name: an example
shell:
cmd: |
docker build -t current_dir .
echo "Hello World"
date
chdir: /home/vagrant/