Ad-hoc Commands are used in Ansible to execute tasks instantly, and you need not save them for later use. This article is all about Ansible Ad-hoc Command.
There are multiple tasks in Ansible where you donโt need to write a separate Ansible playbook for it; you can just run an ansible ad-hoc command for that task. These are one-liner command to perform a single task on the target host. These commands are present in /usr/bin/ansible
.
What is Ansible Ad-hoc Command?
An Ansible ad-hoc command is a useful tool that allows you to execute a single task on a group of servers without needing to create a full playbook. These commands are great for performing simple tasks like checking the status of a service or quickly running a command. However, for more complex tasks like software installations, it’s usually better to use a playbook.
A single line of code containing the relevant information, such as the desired module name and any parameters that must be supplied to it, is entered to run an ad-hoc command.
The syntax for an Ansible ad-hoc command is as follows:
ansible <hosts> -m <module> -a "<arguments>"
Here:
- <hosts> is a comma-separated list of target hosts,
- <module> is the name of the Ansible module to use, and
- <arguments> are any arguments to be passed to the module.
For example, if you wanted to check the disk space on a group of servers, you could use the df -h command with the shell module, like this:
ansible web_servers -m shell -a "df -h"
The shell module would run the df -h command on all servers in the web_servers group. Then, you’ll be able to see the output from each server in your console. It’s super easy and efficient!
Why use Ansible ad-hoc commands?
Apart from being quick and easy to use, ad-hoc commands are perfect for simple, one-time tasks that don’t require a lot of complexity. Also, they’re a great way to try out new modules or commands before adding them to a playbook. This can help you avoid mistakes and save time in the long run.
If youโre troubleshooting an issue on a server, you can use them to check the status of a service, view log files, or perform other diagnostic tasks.
Moreover, ad-hoc commands are also flexible! You can use them for all kinds of tasks, like installing packages, copying files, or running commands on multiple servers at once.
If you want to make server management easier and more efficient, Ansible ad-hoc commands are the way to go!
Here are some of the ways you can use them:
- Rebooting servers
- Managing files
- Managing packages
- Managing users and groups
- Managing services
- Gathering facts
- Patterns and ad-hoc commands
Tasks like pinging all the hosts to check if they are running, copying a file, rebooting servers, and installing a package can be easily done through Ansible Ad-hoc Commands. Here is a list of fundamental Ansible Ad-hoc commands which you must know.
Basic Commands
The ad-hoc command below runs a ping module on all the hosts in the inventory file. Here -m
is the option for a module.
<strong>root@geekflare:/home/geekflare# ansible all -m ping</strong>
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
The command mentioned below runs setup module on a group of hosts โ Client present in the inventory file ‘/etc/ansible/hosts’.
root@geekflare:/home/geekflare# ansible Client -m setup -a "filter=ansible_distribution*"
node1 | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "Ubuntu",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/os-release",
"ansible_distribution_file_variety": "Debian",
"ansible_distribution_major_version": "18",
"ansible_distribution_release": "cosmic",
"ansible_distribution_version": "18.10",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
The command below is used to prompt SSH password authentication. You need to add โask-pass
option at the end of the command. After running the command, it will ask you to enter the SSH password.
root@geekflare:/home/geekflare# ansible Client -m ping --ask-pass
SSH password:
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
The command below gives you the feature of running ad-hoc commands as a non-root user with root privileges. The option --become
gives the root privileges and -K
option asks for the password.
root@geekflare:/home/geekflare# ansible Client -m shell -a 'fdisk -l' -u geekflare --become -K
BECOME password:
node1 | CHANGED | rc=0 >>
Disk /dev/loop0: 14.5 MiB, 15208448 bytes, 29704 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop2: 42.1 MiB, 44183552 bytes, 86296 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop3: 149.9 MiB, 157184000 bytes, 307000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop5: 140.7 MiB, 147501056 bytes, 288088 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop6: 151.2 MiB, 158584832 bytes, 309736 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/loop7: 14.8 MiB, 15458304 bytes, 30192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/sda: 500 GiB, 536870912000 bytes, 1048576000 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xcef957f5
Device Boot Start End Sectors Size Id Type
/dev/sda1 2048 462639103 462637056 220.6G 83 Linux
/dev/sda2 * 462639104 464592895 1953792 954M 83 Linux
/dev/sda3 464592896 482168831 17575936 8.4G 82 Linux swap / Solaris
/dev/sda4 482168832 1048573951 566405120 270.1G 83 Linux
Disk /dev/loop8: 4 MiB, 4218880 bytes, 8240 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
This ad-hoc command is used to reboot the system with -f option for defining the number of forks.
root@geekflare:/home/geekflare# ansible Client -a "/sbin/reboot" -f 1
File Transfer
The ansible ad-hoc command below is used to copy a file from a source to a destination for a group of hosts (Client) defined in the inventory file. After you enter the password, the output with โchangeโ parameter will be โtrueโ, which means the file has been copied to the destination.
root@geekflare:/home/geekflare# ansible Client -m copy -a 'src=/home/geekflare/nginx.yml dest=/home/geekflare/Desktop/ owner=root mode=0644' -u root --become -K
BECOME password:
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "5631822866afd5f19b928edb3ba018385df22dd3",
"dest": "/home/geekflare/Desktop/nginx.yml",
"gid": 0,
"group": "root",
"md5sum": "0d6ffe1069fc25ad4f8ad700277c4634",
"mode": "0644",
"owner": "root",
"size": 280,
"src": "/root/.ansible/tmp/ansible-tmp-1562253463.3-214622150088155/source",
"state": "file",
"uid": 0
}
Run the below command to verify if the copy module worked correctly or not. The copied file should come at the destination mentioned in the previous command.
root@geekflare:/home/geekflare# ls Desktop/
nginx.yml
I am creating a new directory to run fetch module n next ad-hoc command.
root@geekflare:/home/geekflare# mkdir example
root@geekflare:/home/geekflare# ls
Desktop Documents example examples.desktop nginx_new.yml nginx.yml
The ansible ad-hoc command below is used to download a file from a host defined in the command. In this command, we are downloading a file using fetch module from node1 server to a local destination on ansible node.
root@geekflare:/home/geekflare# ansible node1 -m fetch -a 'src=/etc/sudoers.d/nginx.yml dest=/home/geekflare/example/ flat=yes'
node1 | SUCCESS => {
"changed": false,
"checksum": "5631822866afd5f19b928edb3ba018385df22dd3",
"dest": "/home/geekflare/example/nginx.yml",
"file": "/etc/sudoers.d/nginx.yml",
"md5sum": "0d6ffe1069fc25ad4f8ad700277c4634"
}
Check if the file got downloaded or not at the destination mentioned in the command.
root@geekflare:/home/geekflare# ls example
nginx.yml
Manage Packages
The command mentioned below installs nginx on a group of hosts (Client) mentioned using an apt module.
root@geekflare:/home/geekflare# ansible Client -m apt -a 'name=nginx state=latest' --become
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"cache_update_time": 1562411227,
"cache_updated": false,
"changed": false
}
The command mentioned below removes nginx on a group of hosts (Client) using apt module and purges all the related configurations.
root@geekflare:/home/geekflare# ansible Client -m apt -a 'name=nginx state=absent purge=yes' --become
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"stderr": "",
"stderr_lines": [],
"stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nThe following packages were automatically installed and are no longer required:\n libnginx-mod-http-geoip libnginx-mod-http-image-filter\n libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream\n nginx-common nginx-core\nUse 'sudo apt autoremove' to remove them.\nThe following packages will be REMOVED:\n nginx*\n0 upgraded, 0 newly installed, 1 to remove and 241 not upgraded.\nAfter this operation, 44.0 kB disk space will be freed.\n(Reading database ... \r(Reading database ... 5%\r(Reading database ... 10%\r(Reading database ... 15%\r(Reading database ... 20%\r(Reading database ... 25%\r(Reading database ... 30%\r(Reading database ... 35%\r(Reading database ... 40%\r(Reading database ... 45%\r(Reading database ... 50%\r(Reading database ... 55%\r(Reading database ... 60%\r(Reading database ... 65%\r(Reading database ... 70%\r(Reading database ... 75%\r(Reading database ... 80%\r(Reading database ... 85%\r(Reading database ... 90%\r(Reading database ... 95%\r(Reading database ... 100%\r(Reading database ... 180191 files and directories currently installed.)\r\nRemoving nginx (1.15.5-0ubuntu2.1) ...\r\n",
"stdout_lines": [
"Reading package lists...",
"Building dependency tree...",
"Reading state information...",
"The following packages were automatically installed and are no longer required:",
" libnginx-mod-http-geoip libnginx-mod-http-image-filter",
" libnginx-mod-http-xslt-filter libnginx-mod-mail libnginx-mod-stream",
" nginx-common nginx-core",
"Use 'sudo apt autoremove' to remove them.",
"The following packages will be REMOVED:",
" nginx*",
"0 upgraded, 0 newly installed, 1 to remove and 241 not upgraded.",
"After this operation, 44.0 kB disk space will be freed.",
"(Reading database ... ",
"(Reading database ... 5%",
"(Reading database ... 10%",
"(Reading database ... 15%",
"(Reading database ... 20%",
"(Reading database ... 25%",
"(Reading database ... 30%",
"(Reading database ... 35%",
"(Reading database ... 40%",
"(Reading database ... 45%",
"(Reading database ... 50%",
"(Reading database ... 55%",
"(Reading database ... 60%",
"(Reading database ... 65%",
"(Reading database ... 70%",
"(Reading database ... 75%",
"(Reading database ... 80%",
"(Reading database ... 85%",
"(Reading database ... 90%",
"(Reading database ... 95%",
"(Reading database ... 100%",
"(Reading database ... 180191 files and directories currently installed.)",
"Removing nginx (1.15.5-0ubuntu2.1) ..."
]
}
Manage Services
The ansible ad-hoc command below runs service module to start nginx on the host. The state value should be started.
root@geekflare:/home/geekflare# ansible Client -m service -a 'name=nginx state=started enabled=yes' --become
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"enabled": true,
"name": "nginx",
"state": "started",
"status": {
"ActiveEnterTimestamp": "Sat 2019-07-06 08:28:02 EDT",
"ActiveEnterTimestampMonotonic": "31411371",
"ActiveExitTimestampMonotonic": "0",
"ActiveState": "active",
"After": "sysinit.target system.slice systemd-journald.socket basic.target network.target",
"AllowIsolate": "no",
"AmbientCapabilities": "",
"AssertResult": "yes",
"AssertTimestamp": "Sat 2019-07-06 08:27:59 EDT",
"AssertTimestampMonotonic": "27694868",
"Before": "multi-user.target shutdown.target",
"BlockIOAccounting": "no",
"BlockIOWeight": "[not set]",
"CapabilityBoundingSet": "cap_chown cap_dac_override cap_dac_read_search cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin cap_net_raw cap_ipc_lock cap_ipc_owner cap_sys_module cap_sys_rawio cap_sys_chroot cap_sys_ptrace cap_sys_pacct cap_sys_admin cap_sys_boot cap_sys_nice cap_sys_resource cap_sys_time cap_sys_tty_config cap_mknod cap_lease cap_audit_write cap_audit_control cap_setfcap cap_mac_override cap_mac_admin cap_syslog cap_wake_alarm cap_block_suspend",
"CollectMode": "inactive",
"ConditionResult": "yes",
"ConditionTimestamp": "Sat 2019-07-06 08:27:59 EDT",
"ConditionTimestampMonotonic": "27694867",
"ConfigurationDirectoryMode": "0755",
"Conflicts": "shutdown.target",
"ControlGroup": "/system.slice/nginx.service",
"ControlPID": "0",
"ExecMainStartTimestamp": "Sat 2019-07-06 08:28:02 EDT",
"ExecMainStartTimestampMonotonic": "31411353",
"ExecMainStatus": "0",
"ExecReload": "{ path=/usr/sbin/nginx ; argv[]=/usr/sbin/nginx -g daemon on; master_process on; -s reload ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStart": "{ path=/usr/sbin/nginx ; argv[]=/usr/sbin/nginx -g daemon on; master_process on; ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStartPre": "{ path=/usr/sbin/nginx ; argv[]=/usr/sbin/nginx -t -q -g daemon on; master_process on; ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStop": "{ path=/sbin/start-stop-daemon ; argv[]=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid ; ignore_errors=yes ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"FailureAction": "none",
"FileDescriptorStoreMax": "0",
"FragmentPath": "/lib/systemd/system/nginx.service",
"GID": "[not set]",
"GuessMainPID": "yes",
"IOAccounting": "no",
"IOSchedulingClass": "0",
"IOSchedulingPriority": "0",
"IOWeight": "[not set]",
}
}
The below runs service module to stop nginx on the host. The state value changes to stopped.
root@geekflare:/home/geekflare# ansible Client -m service -a 'name=nginx state=stopped' --become
node1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "nginx",
"state": "stopped",
"status": {
"ActiveEnterTimestamp": "Sat 2019-07-06 08:28:02 EDT",
"ActiveEnterTimestampMonotonic": "31411371",
"ActiveExitTimestampMonotonic": "0",
"ActiveState": "active",
"After": "sysinit.target system.slice systemd-journald.socket basic.target network.target",
"AllowIsolate": "no",
"AmbientCapabilities": "",
"AssertResult": "yes",
"AssertTimestamp": "Sat 2019-07-06 08:27:59 EDT",
"AssertTimestampMonotonic": "27694868",
"Before": "multi-user.target shutdown.target",
"BlockIOAccounting": "no",
"BlockIOWeight": "[not set]",
"CPUAccounting": "no",
"CPUQuotaPerSecUSec": "infinity",
"CanReload": "yes",
"CanStart": "yes",
"CanStop": "yes",
"CapabilityBoundingSet": "cap_chown cap_dac_override cap_dac_read_search cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin cap_net_raw cap_ipc_lock cap_ipc_owner cap_sys_module cap_sys_rawio cap_sys_chroot cap_sys_ptrace cap_sys_pacct cap_sys_admin cap_sys_boot cap_sys_nice cap_sys_resource cap_sys_time cap_sys_tty_config cap_mknod cap_lease cap_audit_write cap_audit_control cap_setfcap cap_mac_override cap_mac_admin cap_syslog cap_wake_alarm cap_block_suspend",
"CollectMode": "inactive",
"ConditionResult": "yes",
"ConditionTimestamp": "Sat 2019-07-06 08:27:59 EDT",
"ConditionTimestampMonotonic": "27694867",
"ConfigurationDirectoryMode": "0755",
"Conflicts": "shutdown.target",
"ControlGroup": "/system.slice/nginx.service",
"ControlPID": "0",
"DefaultDependencies": "yes",
"Delegate": "no",
"Description": "A high performance web server and a reverse proxy server",
"DevicePolicy": "auto",
"Documentation": "man:nginx(8)",
"DynamicUser": "no",
}
}
Checking the System
The ansible ad-hoc command mentioned below runs a shell module to check the disk available at root partitions.
root@geekflare:/home/geekflare# ansible Client -m shell -a 'df -h /dev/sda2' --become
node1 | CHANGED | rc=0 >>
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 923M 113M 748M 14% /boot
This command mentioned below runs a shell module to check the free memory (RAM) on the host.
root@geekflare:/home/geekflare# ansible Client -m shell -a 'free -m' --become
node1 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 5101 854 2760 27 1487 3947
Swap: 8581 0 8581
This command checks the uptime of each server running.
root@geekflare:/home/geekflare# ansible Client -a "uptime"
node1 | CHANGED | rc=0 >>
11:31:17 up 1 day, 2:40, 2 users, load average: 0.23, 0.05, 0.02
Gathering Facts
The ansible ad-hoc command below will give you all the ad-hoc information of your system, including all the variables present in the system.
root@geekflare:/home/geekflare# ansible all -m setup
node1 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.17.0.1",
"10.0.2.15"
],
"ansible_all_ipv6_addresses": [
"fe80::763e:c0b4:14df:b273"
],
"ansible_apparmor": {
"status": "enabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "12/01/2006",
"ansible_bios_version": "VirtualBox",
"ansible_cmdline": {
"BOOT_IMAGE": "/vmlinuz-4.18.0-25-generic",
"quiet": true,
"ro": true,
"root": "UUID=5f85d8b7-0ab2-48c9-9e6e-4ecfbcbdaa83",
"splash": true
},
"ansible_date_time": {
"date": "2019-07-07",
"day": "07",
"epoch": "1562525628",
"hour": "14",
"iso8601": "2019-07-07T18:53:48Z",
"iso8601_basic": "20190707T145348850596",
"iso8601_basic_short": "20190707T145348",
"iso8601_micro": "2019-07-07T18:53:48.850697Z",
"minute": "53",
"month": "07",
"second": "48",
"time": "14:53:48",
"tz": "EDT",
"tz_offset": "-0400",
"weekday": "Sunday",
"weekday_number": "0",
"weeknumber": "26",
"year": "2019"
},
"ansible_default_ipv4": {
"address": "10.0.2.15",
"alias": "enp0s3",
"broadcast": "10.0.2.255",
"gateway": "10.0.2.2",
"interface": "enp0s3",
"macaddress": "08:00:27:68:64:9a",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.2.0",
"type": "ether"
},
"ansible_default_ipv6": {},
"ansible_device_links": {
"ids": {
"sda": [
"ata-VBOX_HARDDISK_VB3a0a2351-0b6c0ed5"
],
"sda1": [
"ata-VBOX_HARDDISK_VB3a0a2351-0b6c0ed5-part1"
],
"sda2": [
"ata-VBOX_HARDDISK_VB3a0a2351-0b6c0ed5-part2"
],
"sda3": [
"ata-VBOX_HARDDISK_VB3a0a2351-0b6c0ed5-part3"
],
"sda4": [
"ata-VBOX_HARDDISK_VB3a0a2351-0b6c0ed5-part4"
],
"sr0": [
"ata-VBOX_CD-ROM_VB2-01700376"
]
},
"labels": {
"sr0": [
"VBox_GAs_6.0.2"
]
},
"masters": {},
"uuids": {
"sda1": [
"5f85d8b7-0ab2-48c9-9e6e-4ecfbcbdaa83"
],
"sda2": [
"b8b7f87b-c3bf-48ed-a44c-f9b3ce0afbe5"
],
"sda3": [
"a6c77fa6-e292-4a0d-b21f-8804f1949bbd"
],
"sda4": [
"8207f970-4d9a-47db-a5d5-f620e5b17b7b"
],
"sr0": [
"2019-01-14-14-57-19-65"
]
}
},
"ansible_devices": {
"loop0": {
"holders": [],
"host": "",
"links": {
"ids": [],
"labels": [],
"masters": [],
"uuids": []
},
"model": null,
"partitions": {},
"removable": "0",
"rotational": "1",
"sas_address": null,
"sas_device_handle": null,
"scheduler_mode": "none",
"sectors": "29704",
"sectorsize": "512",
"size": "14.50 MB",
"support_discard": "4096",
"vendor": null,
"virtual": 1
},
"loop1": {
"holders": [],
"host": "",
"links": {
"ids": [],
"labels": [],
"masters": [],
"uuids": []
},
"model": null,
"partitions": {},
"removable": "0",
"rotational": "1",
"sas_address": null,
"sas_device_handle": null,
"scheduler_mode": "none",
"sectors": "0",
"sectorsize": "512",
"size": "0.00 Bytes",
"support_discard": "4096",
"vendor": null,
"virtual": 1
},
}
So, that was all about Ansible Ad-hoc Commands. Go ahead and try these commands on your ansible setup. Use these commands to run ansible modules without writing any Ansible playbook to perform those tasks. Drop a comment if you face any issue in running these commands.