Ansible Ad-Hoc Commands

Following from Ansible Installation and Setup, we'll continue with Ansible ad-hoc modules.

Ansible Documentation

There is extensive documentation on Ansible available at https://docs.ansible.com/

The current version of Ansible at the time of writing is version 2.9.

Be aware that there are a large number of modules maintained by the Ansible core group and even more maintained by third parties.

Here are all of the modules by category:

Some basic ones are the command and file modules:

The Ansible documentation is typically quite good and will give examples on any module that it has.

Command-line help

You can also use the ansible-doc command on the command line for an offline version of the examples and core usage.

An example of command line usage for ansible-doc is as follows:

ansible-doc -t module file

-t is the command argument for topic.

When you start making complex playbooks with variable substitution and conditionals, it can be very handy to have this quick searchable reference.

Sample Ansible hosts file

The Ansible hosts file is a list of IPs/hostnames in groups that commands can be run against. This file can be in .ini or .yaml format.

By default, the base inventory file is located here: /etc/ansible/hosts

An example hosts file in .ini format would look like this:

[csn]
172.29.0.3
[elasticsearch]
172.29.1.20
172.29.1.21
[es1]
172.29.1.20
[es2]
172.29.1.21
[gateway]
172.29.1.26
[allcaringo]
172.29.0.3
172.29.1.20
172.29.1.21
172.29.1.26

In the example above, the IP addresses could be replaced with host names as long as the Ansible host can resolve the host.

Use ad-hoc commands on hosts

Let's go through a few examples using our host Inventory above.

Because we've already seen the ping module, let's cover something more useful: the service module.

ansible elasticsearch -m service -a "name=elasticsearch state=started"

This command is a little different from the ping module because it takes additional arguments.

The "name=" could be any service. The state could be started, stopped, reloaded, or restarted.

When we use the service module against a group "elasticsearch", then any action we're attempting is carried out against all members of that group.

If we targeted "es1", then it would only run the command against the IP addresses or hostnames defined under "es1".

That command would take this form:

ansible es1 -m service -a "name=elasticsearch state=started"

If we wanted to restart our "cloudgateway" service, the command would look like this:

ansible cloudgateway -m service -a "name=cloudgateway state=restarted"

By default, Ansible will run commands against up to 5 hosts at a time. This limit can be increased or decreased. In this case, we only have 1 server in our cloudgateway group, but let's say we had more and wanted to restart them one by one.

To force Ansible to run the command against one host at a time, add the -f flag:

ansible cloudgateway -m service -a "name=cloudgateway state=restarted" -f 1

This will set the number of parallel tasks to 1, so it will only run against 1 host at a time, regardless of how many hosts there are in the group.

Install a package and start it

Following is a simple workflow to demonstrate how powerful Ansible can be.

The modules we will use are:

  • yum
  • service

We're going to install a new package and start its service.  

First, let's install the monit package with yum:

ansible cloudgateway -m yum -a "name=monit state=latest"

The yum package will then attempt to install monit on all of the hosts that belong to the cloudgateway group.

The output will be something like this:

[root@caringomanagementserver ~]# ansible gateway -m yum -a "name=monit state=latest"
172.29.1.26 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "monit"
        ], 
        "updated": []
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror, langpacks\n
Loading mirror speeds from cached hostfile\n
 * base: mirror.sov.uk.goscomb.net\n
 * epel: mirrors.coreix.net\n * extras: ftp.heanet.ie\n
 * updates: mirror.sov.uk.goscomb.net\n
Resolving Dependencies\n
--> Running transaction check\n
---> Package monit.x86_64 0:5.26.0-1.el7 will be installed\n
--> Finished Dependency Resolution\n
\n
Dependencies Resolved\n
\n
================================================================================\n
 Package         Arch             Version                  Repository      Size \n
================================================================================\n
Installing:\n
 monit           x86_64           5.26.0-1.el7             epel           321 k \n
\n
Transaction Summary\n
================================================================================\n
Install  1 Package\n
\n
Total download size: 321 k\n
Installed size: 822 k\n
Downloading packages:\n
Running transaction check\n
Running transaction test\n
Transaction test succeeded\n
Running transaction\n
  Installing : monit-5.26.0-1.el7.x86_64                                    1/1 \n
  Verifying  : monit-5.26.0-1.el7.x86_64                                    1/1 \n
\n
Installed:\n
  monit.x86_64 0:5.26.0-1.el7                                                   \n
\nComplete!\n
"
    ]
}

With the service now installed, we can then enable it:

[root@caringomanagementserver ~]# ansible gateway -m service -a "name=monit enabled=yes state=started"
172.29.1.26 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "enabled": true, 
    "name": "monit", 
    "state": "started", 
    "status": {
        "ActiveEnterTimestampMonotonic": "0", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "inactive", 
        "After": "systemd-journald.socket system.slice basic.target network.target", 
        "AllowIsolate": "no", 
        "AmbientCapabilities": "0", 
        "AssertResult": "no", 
        "AssertTimestampMonotonic": "0", 
        "Before": "shutdown.target", 
        "BlockIOAccounting": "no", 
        "BlockIOWeight": "18446744073709551615", 
        "CPUAccounting": "no", 
        "CPUQuotaPerSecUSec": "infinity", 
        "CPUSchedulingPolicy": "0", 
        "CPUSchedulingPriority": "0", 
        "CPUSchedulingResetOnFork": "no", 
        "CPUShares": "18446744073709551615", 
        "CanIsolate": "no", 
        "CanReload": "yes", 
        "CanStart": "yes", 
        "CanStop": "yes", 
        "CapabilityBoundingSet": "18446744073709551615", 
        "ConditionResult": "no", 
        "ConditionTimestampMonotonic": "0", 
        "Conflicts": "shutdown.target", 
        "ControlPID": "0", 
        "DefaultDependencies": "yes", 
        "Delegate": "no", 
        "Description": "Pro-active monitoring utility for unix systems", 
        "DevicePolicy": "auto", 
        "ExecMainCode": "0", 
        "ExecMainExitTimestampMonotonic": "0", 
        "ExecMainPID": "0", 
        "ExecMainStartTimestampMonotonic": "0", 
        "ExecMainStatus": "0", 
        "ExecReload": "{ path=/usr/bin/monit ; argv[]=/usr/bin/monit reload ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStart": "{ path=/usr/bin/monit ; argv[]=/usr/bin/monit -I ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStop": "{ path=/usr/bin/monit ; argv[]=/usr/bin/monit quit ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "FailureAction": "none", 
        "FileDescriptorStoreMax": "0", 
        "FragmentPath": "/usr/lib/systemd/system/monit.service", 
        "GuessMainPID": "yes", 
        "IOScheduling": "0", 
        "Id": "monit.service", 
        "IgnoreOnIsolate": "no", 
        "IgnoreOnSnapshot": "no", 
        "IgnoreSIGPIPE": "yes", 
        "InactiveEnterTimestampMonotonic": "0", 
        "InactiveExitTimestampMonotonic": "0", 
        "JobTimeoutAction": "none", 
        "JobTimeoutUSec": "0", 
        "KillMode": "control-group", 
        "KillSignal": "15", 
        "LimitAS": "18446744073709551615", 
        "LimitCORE": "18446744073709551615", 
        "LimitCPU": "18446744073709551615", 
        "LimitDATA": "18446744073709551615", 
        "LimitFSIZE": "18446744073709551615", 
        "LimitLOCKS": "18446744073709551615", 
        "LimitMEMLOCK": "65536", 
        "LimitMSGQUEUE": "819200", 
        "LimitNICE": "0", 
        "LimitNOFILE": "4096", 
        "LimitNPROC": "63445", 
        "LimitRSS": "18446744073709551615", 
        "LimitRTPRIO": "0", 
        "LimitRTTIME": "18446744073709551615", 
        "LimitSIGPENDING": "63445", 
        "LimitSTACK": "18446744073709551615", 
        "LoadState": "loaded", 
        "MainPID": "0", 
        "MemoryAccounting": "no", 
        "MemoryCurrent": "18446744073709551615", 
        "MemoryLimit": "18446744073709551615", 
        "MountFlags": "0", 
        "Names": "monit.service", 
        "NeedDaemonReload": "no", 
        "Nice": "0", 
        "NoNewPrivileges": "no", 
        "NonBlocking": "no", 
        "NotifyAccess": "none", 
        "OOMScoreAdjust": "0", 
        "OnFailureJobMode": "replace", 
        "PermissionsStartOnly": "no", 
        "PrivateDevices": "no", 
        "PrivateNetwork": "no", 
        "PrivateTmp": "no", 
        "ProtectHome": "no", 
        "ProtectSystem": "no", 
        "RefuseManualStart": "no", 
        "RefuseManualStop": "no", 
        "RemainAfterExit": "no", 
        "Requires": "basic.target system.slice", 
        "Restart": "no", 
        "RestartUSec": "100ms", 
        "Result": "success", 
        "RootDirectoryStartOnly": "no", 
        "RuntimeDirectoryMode": "0755", 
        "SameProcessGroup": "no", 
        "SecureBits": "0", 
        "SendSIGHUP": "no", 
        "SendSIGKILL": "yes", 
        "Slice": "system.slice", 
        "StandardError": "inherit", 
        "StandardInput": "null", 
        "StandardOutput": "journal", 
        "StartLimitAction": "none", 
        "StartLimitBurst": "5", 
        "StartLimitInterval": "10000000", 
        "StartupBlockIOWeight": "18446744073709551615", 
        "StartupCPUShares": "18446744073709551615", 
        "StatusErrno": "0", 
        "StopWhenUnneeded": "no", 
        "SubState": "dead", 
        "SyslogLevelPrefix": "yes", 
        "SyslogPriority": "30", 
        "SystemCallErrorNumber": "0", 
        "TTYReset": "no", 
        "TTYVHangup": "no", 
        "TTYVTDisallocate": "no", 
        "TasksAccounting": "no", 
        "TasksCurrent": "18446744073709551615", 
        "TasksMax": "18446744073709551615", 
        "TimeoutStartUSec": "1min 30s", 
        "TimeoutStopUSec": "1min 30s", 
        "TimerSlackNSec": "50000", 
        "Transient": "no", 
        "Type": "simple", 
        "UMask": "0022", 
        "UnitFilePreset": "disabled", 
        "UnitFileState": "disabled", 
        "WatchdogTimestampMonotonic": "0", 
        "WatchdogUSec": "0"
    }
}

As you can see, a considerable amount of information is presented related to service start.

Another argument we pass in the above command is "enabled=yes", which tells the service module to always start the service on reboot, effectively a "systemctl enable monit" command.

Check status via monit

Lastly we'll run the command module to check the status via monit.

The command module passes a command on the command line:

[root@caringoadminserver ~]# ansible gateway -m command -a "monit status"
172.29.1.26 | CHANGED | rc=0 >>
Monit 5.26.0 uptime: 4m

System 'swarmcontentgateway'
status OK
monitoring status Monitored
monitoring mode active
on reboot start
load average [0.00] [0.01] [0.05]
cpu 0.0%us 0.0%sy 0.0%wa
memory usage 207.0 MB [1.3%]
swap usage 0 B [0.0%]
uptime 3d 1h 54m
boot time Mon, 16 Mar 2020 05:08:18
data collected Thu, 19 Mar 2020 07:02:55
[root@caringoadminserver ~]#

While the command module is useful for running single commands via the command line, it doesn't run a full shell. This means operations such as console redirection and variable passing may not work as expected. For those use cases, it may be better to run the modules shell, raw, or script.

© DataCore Software Corporation. · https://www.datacore.com · All rights reserved.