Ansible

How to Use the Ansible Shell Module

Ansible is widely used as an automation engine for IT needs such as configuration management, cloud provisioning, and much more. Automation sounds great, but how does Ansible achieve it? It uses “modules” which are responsible for the automation. Without these modules, a user would have to use ad hoc commands to perform tasks.

However, ad hoc commands are not reusable. Sure, they provide you with a way to quickly run individual tasks, but they can’t be reused. An analogy could be drawn where the playbook mode is like a shell script, whereas individual commands are one-liners.

Speaking of shell, Ansible has a shell module too. This module is used to run shell commands on target systems. In this guide, we will go over the Ansible shell module and demonstrate examples of how it can be used.

What is the Shell Module?

The Ansible shell module allows the user to run complex commands with redirection, pipes, etc. It takes a command name, its arguments with white space delimiters and runs it on remote hosts.

It may sound like the exact same thing as the Ansible command module, but the difference is that it runs the commands on the host using a shell. The shell module also has access to environment variables and special operators such as | < > & ; etc. Even better, you can run entire scripts using the shell module. Nonetheless, it is common knowledge among Ansible users that the command module is a safer and more predictable option than the shell module.

Finally, it is important to keep in mind that this module only works with Linux systems. Windows users can use ansible.windows.win_shell in its place. With that said, let’s get into the details of the Ansible shell module.

Using the Ansible Shell Module

Before we start running commands and scripts, let’s take a look at the parameters you will need to pass values to while using this module.

  • chdir – Changes the current directory before execution.
  • cmd – A string containing the command to be executed, along with its arguments.
  • executable – Requires an absolute path to change the shell you’re using.
  • removes – Takes a filename. Used to exclude steps when a file doesn’t exist.
  • stdin – Lets the user set the stdin of a command to a specific value.
  • warn – Takes yes (default) or no, enabling or disabling task warnings.

With that out of the way, let’s get to some examples of how to use Ansible shell.

Example 1: Changing the Working Directory

If you want to change the working directory before executing a command, here’s how it would be done.

- name: Changing the working directory to myDir

ansible.builtin.shell
: myScript.sh >> myLog.txt

args
:

chdir
: myDir/

Now that we’ve created a playbook, you can run it using the Linux terminal by running:

ansible-playbook testbook.yml

Example 2: Extracting Command Output

If you want to capture and store the return value of a shell command, the register keyword may be used.

- name: Creating a .txt file in $HOME

shell
: echo "Save me!" > $HOME/test.txt

register
: shell_output

- debug
: var=shell_output

Example 3: Checking the Date

Let’s start by checking the date on our remote server called test. Note how the syntax of the shell module is different here. This is just another way to use the Ansible shell module.

- name: Checking the date

shell
:

"date"

register
: datecmd

tags
: datecmd

- debug
: msg="{{datecmd.stdout}}"

We have used the simple date command to check the date on a remote system. Moreover, the output of the command (the date itself) is being returned to a register named datecmd. Finally, we display the contents of the register variable datecmd by printing its stdout attribute.

Example 4: Running Multiple Commands

In this example, we will create some text files in a temporary directory.

tasks:

- name
: Creating multiple files

ansible.builtin.shell
: |

echo "I am file 1" > /tmp/myFile1.txt

echo "I am file 2"> /tmp/myFile2.txt

echo "I am file 3" > /tmp/myFile3.txt

become: true

args:

chdir: /var/log

Here, we’ve used shell code to create three files, namely, myFile1, myFile2, and myFile3. The become:true line allows you to “become” the user of the remote host. Finally, we pass a chdir argument and change the directory.

Example 5: Applying Redirection & Pipe

Now, let’s see how pipes and redirection works in the Ansible shell module. We will run a simple ls command with some preprocessing through awk. Moreover, we use sed to remove empty lines. In the end, we will redirect the output to a text file.

- name: Take a list of the directory and feed it to a file

shell
:

" ls -lrt /apps|awk '{print $9}'|sed '/^$/d' > /tmp/myDir.txt "

register
: lsout

tags
: lsout

- name
: Display the file

shell
: cat /tmp/dirlist.txt

register
: displaylist

- debug
: msg="{{displaylist.stdout_lines}}"

First, we execute the aforementioned command and store its result in myDir.txt. Afterwards, we use another command cat to save the contents of the file in a register. Finally, this register variable is displayed.

How to Prevent Command Injection?

As we mentioned earlier, the command module is considered a safer way to do things. However, it has somewhat limited functionality. So, how does one use the shell module safely?

You can use the quote filter to protect the variable names you pass to the shell module from command injection. Given below is an example of this sanitization.

- name: Creating a .txt with the quote filter

shell
: echo "I am safe" > $HOME/{{ safeFile | quote }}.txt

It is a good practice to always use the quote filter with your variables. This will keep hackers from changing the command at the runtime. It is a lot like SQL injection, but as long as you take safety precautions, you don’t have to worry!

Conclusion

The Ansible shell module is a versatile and powerful module that increases user control and makes remote configuration much easier. In this article, we’ve looked at what it does, which parameters it has and which arguments it requires, and more. Hopefully, you are now well equipped to use the Ansible shell module.

About the author

Zeeman Memon

Hi there! I'm a Software Engineer who loves to write about tech. You can reach out to me on LinkedIn.