Ansible Command Module Introduction
Ansible Command module is used to execute commands on a remote node.
The Command module, is used mostly to run simple Linux commands on a remote node/server which is part of a host group or Stand alone server mentioned in the host group.
If you want to run Some Simple Shell Commands on the remote server you can use this Ansible command module.
But when there are little complex Shell commands or two commands joined with the PIPE
. you cannot use this command module and you should choose Shell module over this.
Not Just pipe, If you use any of these characters like | > < in your command you should consider using Shell module
Where to use Ansible COMMAND and Where to use Ansible SHELL?
ls -lrt /etc/httpd/conf
is simple and can be executed with Ansible command module
ls -lrt /etc/httpd/conf|awk '{print $9}'
It has PIPE simple in it. you should use Shell module for this command
If you think the Ansible Shell module is what you want. Refer the following article or If you would like to continue with Ansible Command module Continue to read.
Prerequisites
We presume that you have ansible and couple of Virtual machines to test it and we would highly recommend Vagrant Over Traditional Virtual machine like Oracle Virtual box / VMware WorkStation etc.
We have designed this post specific to the commands module.
If you want to know Learn the basics like What is Ansible, What is Vagrant and How to Install and Setup them and build your Local Work Space. Refer this post
Ansible Command Examples
- Get the Uptime of remote server with an ansible command module
- Get the Hostname and version using UNAME
- Check the Disk Usage of Remote server or node using ansible command module
- Restart Apache on the remote server using ansible command module
- Execute a command when a the file exists or not exists ( present or not present) [ Create a file if it does not already exist, Remove the file if it is present or exist]
- Run a Script only if a certain file is present (or) Not Present (EXIST or NOT EXIST )
Here I have two Virtual machines named mwiweb02
and mwivmapp01
grouped in the name of testservers
in an ansible_hosts
file.
Let us quickly list the servers under the host group testservers
.
$ ansible testservers – list -i ansible_hosts hosts (2): mwiweb02 mwivmapp01
Now you can see we have listed the machines/remote servers in the hostgroup named testservers
.
Example1: Get the Uptime of remote servers
We have used command module to run the uptime command and we have given both the ad hoc and the playbook form of execution.
as AD-HOC Command
$ ansible testservers -m command -a uptime -i ansible_hosts
mwivmapp01 | CHANGED | rc=0 >>
10:43:11 up 33 min, 1 user, load average: 0.00, 0.01, 0.05
mwiweb02 | CHANGED | rc=0 >>
10:43:11 up 37 min, 1 user, load average: 0.00, 0.01, 0.03
as Playbook
--- - name: Check the remote host uptime hosts: testservers tasks: - name: Execute the Uptime command over Command module register: uptimeoutput command: "uptime" - debug: var: uptimeoutput.stdout_lines
Execution of Playbook
$ ansible-playbook AnsibleWorkSpace/ansible-command-ex1.yml -i ansible_hosts PLAY [Check the remote host uptime] ************************************************************************************************************************** TASK [Gathering Facts] *************************************************************************************************************************************** ok: [mwiweb02] ok: [mwivmapp01] TASK [Execute the Uptime command over Command module] ******************************************************************************************************** changed: [mwiweb02] changed: [mwivmapp01] TASK [debug] ************************************************************************************************************************************************* ok: [mwiweb02] => { "uptimeoutput.stdout_lines": [ " 11:13:15 up 1:07, 1 user, load average: 0.01, 0.02, 0.04" ] } ok: [mwivmapp01] => { "uptimeoutput.stdout_lines": [ " 11:13:15 up 1:04, 1 user, load average: 0.01, 0.02, 0.05" ] } PLAY RECAP *************************************************************************************************************************************************** mwivmapp01 : ok=3 changed=1 unreachable=0 failed=0 mwiweb02 : ok=3 changed=1 unreachable=0 failed=0
Example2: Get the Hostname and Version of remote servers with UNAME
we have used the command
module and executing an uname -a
command
as AD-HOC command
$ ansible testservers -m command -a "uname -a" -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> Linux mwiweb02 3.10.0-693.11.1.el7.x86_64 #1 SMP Mon Dec 4 23:52:40 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux mwivmapp01 | CHANGED | rc=0 >> Linux mwivmapp01 3.10.0-693.11.1.el7.x86_64 #1 SMP Mon Dec 4 23:52:40 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
As Playbook
--- - name: Check the remote host Hostname, Version, Distribution with UNAME hosts: testservers tasks: - name: Execute the UNAME command register: unameout command: "uname -a" - debug: var: unameout.stdout_lines
Execution of Playbook
$ ansible-playbook AnsibleWorkSpace/ansible-command-ex2.yml -i ansible_hosts PLAY [Check the remote host Hostname, Version, Distribution with UNAME] ************************************************************************************** TASK [Gathering Facts] *************************************************************************************************************************************** ok: [mwiweb02] ok: [mwivmapp01] TASK [Execute the UNAME command] ***************************************************************************************************************************** changed: [mwiweb02] changed: [mwivmapp01] TASK [debug] ************************************************************************************************************************************************* ok: [mwiweb02] => { "unameout.stdout_lines": [ "Linux mwiweb02 3.10.0-693.11.1.el7.x86_64 #1 SMP Mon Dec 4 23:52:40 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux" ] } ok: [mwivmapp01] => { "unameout.stdout_lines": [ "Linux mwivmapp01 3.10.0-693.11.1.el7.x86_64 #1 SMP Mon Dec 4 23:52:40 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux" ] } PLAY RECAP *************************************************************************************************************************************************** mwivmapp01 : ok=3 changed=1 unreachable=0 failed=0 mwiweb02 : ok=3 changed=1 unreachable=0 failed=0
Example3: Check the Disk Usage of Remote server
To get the disk usage, we are using df -h
, here -h
is human readable
As Ad Hoc command
$ ansible testservers -m command -a "df -h" -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 50G 1.2G 49G 3% / devtmpfs 909M 0 909M 0% /dev tmpfs 920M 0 920M 0% /dev/shm tmpfs 920M 8.5M 912M 1% /run tmpfs 920M 0 920M 0% /sys/fs/cgroup /dev/sda1 1014M 171M 844M 17% /boot /dev/mapper/centos-home 28G 33M 28G 1% /home vagrant 112G 88G 24G 79% /vagrant tmpfs 184M 0 184M 0% /run/user/0 tmpfs 184M 0 184M 0% /run/user/1000 mwivmapp01 | CHANGED | rc=0 >> Filesystem Size Used Avail Use% Mounted on /dev/mapper/centos-root 50G 1.4G 49G 3% / devtmpfs 909M 0 909M 0% /dev tmpfs 920M 0 920M 0% /dev/shm tmpfs 920M 8.5M 912M 1% /run tmpfs 920M 0 920M 0% /sys/fs/cgroup /dev/sda1 1014M 171M 844M 17% /boot /dev/mapper/centos-home 28G 33M 28G 1% /home vagrant 112G 88G 24G 79% /vagrant tmpfs 184M 0 184M 0% /run/user/0 tmpfs 184M 0 184M 0% /run/user/1000
As Playbook
--- - name: Check the disk usage of all the file system in the remote servers hosts: testservers tasks: - name: Execute the df command register: dfout command: "df -h" - debug: var: dfout.stdout_lines
Example4: Restart Apache Server using Ansible Command Module
So far, In all the sample we have seen we are using one application server and one web server. Totally two servers.
But in this example, we need to limit our execution only to the web server as we are going to check the restart the apache web server.
this is done using --limit
parameter
As Ad hoc command
$ ansible testservers -m command -a "httpd -k restart" -i ansible_hosts -b – limit mwiweb02 mwiweb02 | CHANGED | rc=0 >>
As Playbook
---
- name: restart apache web server
hosts: testservers
tasks:
- name: restartapache
register: httpdresout
become: yes
command: "httpd -k restart"
when: ansible_hostname == "mwiweb02"
- debug:
var: httpdresout.stdout_lines
Playbook Execution
From the Output you can notice that the application server is skipped
$ ansible-playbook restarthttpd.yml -i ansible_hosts
PLAY [restart apache web server] *************************************************************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************************************************************
ok: [mwiweb02]
ok: [mwivmapp01]
TASK [Execute the df command] ****************************************************************************************************************************************************
skipping: [mwivmapp01]
changed: [mwiweb02]
TASK [debug] *********************************************************************************************************************************************************************
ok: [mwiweb02] => {
"httpdresout.stdout_lines": []
}
ok: [mwivmapp01] => {
"httpdresout.stdout_lines": "VARIABLE IS NOT DEFINED!"
}
PLAY RECAP ***********************************************************************************************************************************************************************
mwivmapp01 : ok=2 changed=0 unreachable=0 failed=0
mwiweb02 : ok=3 changed=1 unreachable=0 failed=0
Example5: Execute a command when a file exists or not exists
There are two most useful parameters in ansible command module such as removes
and creates
removes
- used to tell ansible to Execute the command only if the file exist
creates
- used to tell ansible to Execute the specified command only if the file does not exist
Here we are going to do a very simple file creation and removal based on the file availability or existence. In General using the ansible
command
module, This method of creating and removing the file is not recommended as Ansible has a dedicated module namedfile
to do the same effortlessly.
As Ad hoc command
Remove the file, if it does exist (or) present
$ ansible testservers -a "rm -rf /tmp/testfile removes=/tmp/testfile" -i ansible_hosts mwiweb02 | CHANGED | rc=0 >> mwivmapp01 | CHANGED | rc=0 >>
Create the file, if it does NOT exist (or) absent
$ ansible testservers -a "touch /tmp/testfile creates=/tmp/testfile" -i ansible_hosts mwivmapp01 | CHANGED | rc=0 >> mwiweb02 | CHANGED | rc=0 >>
As Playbook
--- - name: "Validate if a file is present or not present using Ansible Command module" hosts: testservers tasks: - name: "Create a file if it does not exist" command: "touch /tmp/latestfile" args: creates: "/tmp/latestfile" register: createif - name: "Display the file to make sure its created" command: "ls -lrt /tmp/latestfile" register: displayif when: createif is changed - debug: var=displayif.stdout - name: "Remove the file if it exist" command: "rm -rf /tmp/latestfile" args: removes: "/tmp/latestfile" register: removeif
In the playbook
we execute three tasks,
- First one is a create a file if it does not exist
- Second to display if the creation is successful
- Third one is to delete the file if it exists
Playbook Execution Result
this is the execution result or output the preceding playbook. this playbook would return the same result despite run multiple times cause we create, validate and we remove at each execution.
$ ansible-playbook AnsibleWorkSpace/commandex-existnot.yml -i ansible_hosts PLAY [Validate if a file is present or not present using Ansible Command module] ************************************************************************************************* TASK [Gathering Facts] *********************************************************************************************************************************************************** ok: [mwivmapp01] ok: [mwiweb02] TASK [Create a file if it does not exist] **************************************************************************************************************************************** changed: [mwivmapp01] changed: [mwiweb02] TASK [Display the file to make sure its created] ********************************************************************************************************************************* changed: [mwiweb02] changed: [mwivmapp01] TASK [debug] ********************************************************************************************************************************************************************* ok: [mwiweb02] => { "displayif.stdout": "-rw-rw-r--. 1 vagrant vagrant 0 Apr 13 19:55 /tmp/latestfile" } ok: [mwivmapp01] => { "displayif.stdout": "-rw-rw-r--. 1 vagrant vagrant 0 Apr 13 19:55 /tmp/latestfile" } TASK [Remove the file if it exist] *********************************************************************************************************************************************** changed: [mwiweb02] changed: [mwivmapp01] PLAY RECAP *********************************************************************************************************************************************************************** mwivmapp01 : ok=5 changed=3 unreachable=0 failed=0 mwiweb02 : ok=5 changed=3 unreachable=0 failed=0
Example5: Execute or Run the Script when a file exists or not exists
Now for this example let us take something relatable to real world scenario. Like Start the Server instance (or) program if the PID file or LOCK file does not exist
Here is the sample playbook for you to get started. I am giving a general playbook here as I do not want to pick some server/technology of my own which you cannot relate to.
you can feel free to modify the script to your needs as this is just a template.
--- - name: Start of Stop Server instance based on PID/LOCK file availability hosts: appservers tasks: - name: Start the instance when the PID file is not present become: yes become_user: appuser command: "startserver.sh" args: creates: "/path/to/pid/instance.pid" register: startinst - name: Stop the instance when the lock file is present become: yes become_user: appuser command: "stopserver.sh" args: removes: "/path/to/lockfile/instance.lck" register: stopinst
A Quick Additional Info
Ansible Command Module is the Default Module of "Ansible" CLI, Which means, You can write your AD HOC command in both the following forms and both are correct
ansible testservers -m command -a uptime -i ansible_hosts
or
ansible testservers -a uptime -i ansible_hosts
To verify, Try executing ansible – help
in your control master/host and read it through.
Hope this article helps.
Let me know your questions or comments over the comments section below. Rate this article [ratings]
Cheers
Sarav AK
Follow me on Linkedin My Profile Follow DevopsJunction onFacebook orTwitter For more practical videos and tutorials. Subscribe to our channel
Signup for Exclusive "Subscriber-only" Content