Ansible ad-hoc commands

Rajesh GurajalaRajesh Gurajala
14 min read

In Ansible, ad-hoc commands are one-liners you run directly in the terminal to perform quick tasks on your managed nodes β€” without writing a full playbook.

πŸ§ͺ Syntax of an Ad-Hoc Command:

ansible <host-pattern> -m <module-name> -a "<module-options>"

πŸ”Ή Components:

  • ansible: the CLI tool.

  • <host-pattern>: inventory group or host (all, webservers, 192.168.1.10).

  • -m <module-name>: specify which module to use.

  • -a "<args>": module arguments in quotes.

    Let's master Ansible ad-hoc commands where i have grouped the modules by phases.

    πŸ”° PHASE 1: System Basics, File Management

    1. ping – Test connectivity

    2. command – Run system commands

    3. shell – Run shell commands with pipes, variables, redirection

    4. reboot – Reboot systems

    5. setup – Gather system facts

    6. cron – Similar to an alarm

    7. copy – Copy local files to remote

    8. file – Create/delete files/dirs, manage permissions

      • Create file:

      • Create directory:

      • Delete file:

    9. stat – Check if a file exists


πŸ§‘ PHASE 2: Others

  1. user – Create/remove users

  2. yum (RedHat/CentOS)

  3. apt (Debian/Ubuntu)

  4. package (Generic across OSes)

  5. service – Start/stop/restart services


πŸ”° PHASE 1: System Basics, File Management

βœ… ping Module – Purpose

  • Tests whether the target hosts are reachable and can execute Ansible modules (i.e., Python must be installed).

  • Does not use ICMP like Linux ping; it sends a "ping" message over SSH using Python.

If Python is not installed:

Use raw module instead:

    ansible all -m raw -a "apt install -y python3"

πŸ“Œ Basic Syntax

    ansible <host-pattern> -m ping

πŸ”§ Examples

1. Ping all hosts in inventory:

    ansible all -m ping

2. Ping a specific host:

    ansible webserver -m ping

3. Ping using a custom inventory file:

    ansible all -i /path/to/inventory -m ping

4. Ping with verbose output:

    ansible all -m ping -v

Explanation:

  • -v = verbose mode. It shows extra details about what's happening behind the scenes during the ping.

  • You can use more v’s for deeper detail:

    • -v: basic details

    • -vv: connection/debug logs

    • -vvv: Ansible internal debugging

    • -vvvv: full SSH communication

πŸ§ͺ Output:

With -v, you’ll see extra info like:

    Using /etc/ansible/hosts as inventory file
    <192.168.1.10> ESTABLISH SSH CONNECTION
    ...
    192.168.1.10 | SUCCESS => {
        "changed": false,
        "ping": "pong"
    }

Useful for debugging inventory issues or SSH problems.

πŸ§ͺ Expected Output:

    192.168.1.10 | SUCCESS => {
        "changed": false,
        "ping": "pong"
    }

This confirms:

  • Host is reachable via SSH

  • Python is installed and working

βœ… That's all for the ping module.

βœ… command Module – Purpose

  • Used to run simple system commands on remote hosts.

  • It is Default module so no need to use -m for this module commands.

  • Does NOT support shell features like |, >, &&, variables like $HOME.


πŸ“Œ Syntax

ansible <host-pattern> -a "<command>"  # default is command module

πŸ”§ Examples

1. Run uptime on all hosts:

ansible all -a "uptime"

2. List files in /tmp:

ansible all -a "ls -l /tmp"

3. Display current user:

ansible all -a "whoami"

4. Use with specific user:

ansible all -a "hostname" -u raj

❌ What It Can't Do:

  • No shell features like:

      ansible all -a "cat file.txt | grep error"     # ❌ will fail
      ansible all -a "echo $HOME"                    # ❌ will not expand
    
  • For these, use the shell module instead.


πŸ§ͺ Sample Output

192.168.1.10 | SUCCESS | rc=0 >>
 14:02:30 up 10 days,  2 users,  load average: 0.15, 0.10, 0.05

βœ… shell Module – Purpose

  • Runs shell commands on remote hosts.

  • Supports features that command module does not:

    • Pipes (|)

    • Redirection (>, >>)

    • Logical operators (&&, ||)

    • Environment variables ($HOME, $PATH)

    • Bash-specific syntax


πŸ“Œ Syntax

ansible <host-pattern> -m shell -a "<shell-command>"

πŸ”§ Examples

1. Use environment variable:

ansible all -m shell -a "echo $HOME"

2. Use pipe (|) to filter:

ansible all -m shell -a "cat /etc/passwd | grep root"

3. Redirect command output to a file:

ansible all -m shell -a "date > /tmp/current_date.txt"

4. Run multiple commands:

ansible all -m shell -a "mkdir /tmp/demo && touch /tmp/demo/file.txt"

5. Run a script on remote:

ansible all -m shell -a "bash /opt/scripts/cleanup.sh"

6. Append text to a file:

ansible all -m shell -a "echo 'Welcome Raj' >> /tmp/welcome.txt"

πŸ§ͺ Sample Output

192.168.1.10 | SUCCESS | rc=0 >>
/home/raj

⚠️ Best Practices

TipWhy
Prefer command when possibleIt’s safer, avoids shell injection
Use shell only when neededFor pipes, redirection, variables
Quote your shell string carefullyEspecially with $, >, `

βš”οΈ Tricky and Real-World Shell Ad-Hoc Examples


πŸ”Ή 1. Check if a file exists, and create it only if missing

ansible all -m shell -a "test -f /tmp/demo.txt || touch /tmp/demo.txt"

🧠 Explanation:

  • test -f: checks if the file exists

  • || touch: runs touch only if file is missing


πŸ”Ή 2. Append hostname and timestamp to a log file

ansible all -m shell -a "echo \"$(hostname) - $(date)\" >> /tmp/host_log.txt"

🧠 Useful for tracking which host did what and when.


πŸ”Ή 3. Run a multi-line command using a heredoc

ansible all -m shell -a "cat <<EOF > /tmp/script.sh
#!/bin/bash
echo Hello Raj
date
EOF"

🧠 This creates a script file /tmp/script.sh with multiple lines in one go.


πŸ”Ή 4. Delete all .log files older than 7 days

ansible all -m shell -a "find /var/log -name '*.log' -mtime +7 -exec rm -f {} \;"

🧠 This is a common log rotation/cleanup task.


πŸ”Ή 5. Search and count a word in a file

ansible all -m shell -a "grep -o 'error' /var/log/syslog | wc -l"

🧠 Find how many times error occurred in syslog.


πŸ”Ή 6. Check if a port is listening (e.g., 22)

ansible all -m shell -a "ss -tuln | grep ':22'"

🧠 Verifies if SSH is actively listening.


πŸ”Ή 7. Add a cron job via shell

ansible all -m shell -a "(crontab -l ; echo '0 1 * * * /usr/bin/uptime') | crontab -"

🧠 Appends a new cron job without deleting old ones.

βœ… reboot Module – Purpose

  • Gracefully reboots target machines.

  • Waits for them to come back online.

  • Handles SSH reconnects, timeouts, and safe delays.

  • Works better than shell "reboot" or command "reboot" which break SSH and cause task failures.


πŸ“Œ Syntax

ansible <host-pattern> -m reboot

πŸ”§ Basic Examples

1. Reboot all hosts safely:

ansible all -m reboot

2. Reboot with a custom reboot timeout (e.g., 300 seconds):

ansible all -m reboot -a "reboot_timeout=300"

3. Reboot with a delay of 60 seconds before starting:

ansible all -m reboot -a "pre_reboot_delay=60"

4. Reboot and wait for specific port (e.g., SSH port 22):

ansible all -m reboot -a "test_command='ss -tuln | grep :22'"

5. Reboot with both pre-delay and post-delay:

ansible all -m reboot -a "pre_reboot_delay=10 post_reboot_delay=30"

⚠️ Notes

⚠️ CautionDescription
Python RequiredTarget must have Python installed.
SSH Must WorkAnsible waits for SSH to reconnect.
Windows Not SupportedUse win_reboot for Windows systems.

πŸ§ͺ Sample Output

192.168.1.10 | SUCCESS => {
    "changed": true,
    "elapsed": 44
}

This means the system rebooted and was reachable again in 44 seconds.

βœ… setup Module – Purpose

  • Gathers facts (detailed system info) from remote hosts:

    • IP address, hostname, OS, memory, CPU, disk, network interfaces, etc.
  • These facts are useful in:

    • Ad-hoc analysis

    • Conditional logic in playbooks

    • Dynamic inventories


πŸ“Œ Basic Syntax

ansible <host-pattern> -m setup

πŸ”§ Useful Examples

1. Get all system facts from all hosts:

ansible all -m setup

🧠 Outputs a large JSON with hundreds of values.


2. Get facts for a specific host:

ansible web1 -m setup

3. Filter facts using a fact subset (like network, hardware, etc.):

ansible all -m setup -a "filter=ansible_processor"

βœ… Shows only CPU info.

ansible all -m setup -a "filter=ansible_hostname"

βœ… Shows only hostname.

ansible all -m setup -a "filter=ansible_all_ipv4_addresses"

βœ… Shows all IP addresses.


4. Filter facts using a keyword pattern:

ansible all -m setup -a "filter=ansible_*_mb"

βœ… Matches facts like memory size (e.g., ansible_memtotal_mb, ansible_memfree_mb)


πŸ“¦ Commonly Used Fact Names

FactDescription
ansible_hostnameHostname
ansible_all_ipv4_addressesAll IPv4 IPs
ansible_distributionOS name (Ubuntu, CentOS...)
ansible_processor_coresCPU cores
ansible_memtotal_mbTotal RAM in MB
ansible_default_ipv4.addressMain IP address

πŸ§ͺ Sample Output

"ansible_facts": {
  "ansible_hostname": "raj-ubuntu",
  "ansible_memtotal_mb": 8096,
  "ansible_processor_cores": 4,
  "ansible_all_ipv4_addresses": ["192.168.1.10"]
}

πŸ•’ cron Module

βœ… Purpose:

  • Manage cron jobs on remote machines.

πŸ“Œ Syntax (create job):

ansible all -m cron -a "name='<job-name>' minute=0 hour=2 job='/path/to/command'"

πŸ”§ Examples:

1. Add a cron job to run backup at 2 AM daily:

ansible all -m cron -a "name='daily-backup' minute=0 hour=2 job='/usr/local/bin/backup.sh'"

2. Remove the above cron job:

ansible all -m cron -a "name='daily-backup' state=absent"

3. Create a job that runs every 15 minutes:

ansible all -m cron -a "name='check-disk' minute=*/15 job='df -h >> /tmp/disk.log'"

4. Disable a cron job without deleting it:

ansible all -m cron -a "name='check-disk' job='df -h >> /tmp/disk.log' disabled=yes"

πŸ§ͺ Verify cron entries:

ansible all -a "crontab -l"

πŸ“ copy Module – Copy Files to Remote Hosts

βœ… Purpose:

  • Copies files or inline content from the control node (your system) to remote hosts.

πŸ“Œ Basic Syntax:

ansible all -m copy -a "src=/path/to/source dest=/path/to/destination"

πŸ”§ Common Examples:

1. Copy a local file to /tmp on remote host:

ansible all -m copy -a "src=./hello.txt dest=/tmp/hello.txt"

2. Overwrite and set permissions:

ansible all -m copy -a "src=./config.conf dest=/etc/myapp/config.conf mode=0644 owner=root group=root"

3. Send inline content as a file:

ansible all -m copy -a "content='Raj was here!' dest=/tmp/note.txt"

4. Force overwrite (default is true):

ansible all -m copy -a "src=./motd dest=/etc/motd force=yes"

⚠️ Notes:

  • The src path is local to control node, not remote.

  • Use force=no to avoid overwriting files.


🧱 file Module – Manage File/Directory Attributes

βœ… Purpose:

  • Creates files, directories, symlinks.

  • Changes ownership, permissions.

  • Deletes files/directories.


πŸ“Œ Basic Syntax:

ansible all -m file -a "path=/path/to/file state=<state> [other-options]"

πŸ”§ Common Examples:

1. Create a directory:

ansible all -m file -a "path=/opt/demo state=directory mode=0755"

2. Create an empty file:

ansible all -m file -a "path=/tmp/empty.txt state=touch"

3. Delete a file or directory:

ansible all -m file -a "path=/tmp/oldfile.txt state=absent"
ansible all -m file -a "path=/opt/demo state=absent"

4. Change ownership of a file:

ansible all -m file -a "path=/tmp/test.sh owner=raj group=raj mode=0755"

πŸ“‚ stat Module – Purpose

  • Checks file or directory existence and metadata like:

    • exists (True/False)

    • size

    • mode (permissions)

    • mtime, ctime, atime

    • uid, gid, owner, group

    • isdir, islink, etc.


πŸ“Œ Syntax:

ansible all -m stat -a "path=/path/to/file_or_dir"

πŸ”§ Examples:

1. Check if file exists:

ansible all -m stat -a "path=/etc/passwd"

πŸ” Output contains:

"exists": true,
"isreg": true,
"mode": "0644",
"size": 2397

2. Check if directory exists:

ansible all -m stat -a "path=/var/log"

πŸ” Look for:

  • "isdir": true

  • "exists": true


3. Check file permissions and ownership:

ansible all -m stat -a "path=/etc/hosts"

πŸ” Useful for auditing:

"owner": "root",
"group": "root",
"mode": "0644"

🧠 When to Use stat?

Use it when you want to conditionally act based on:

  • File existence

  • Type (file vs dir)

  • Permissions


πŸ§‘ PHASE 2: Others

πŸ‘€ user Module – Purpose

Used to create, modify, or delete user accounts on remote systems.


πŸ“Œ Syntax:

ansible all -m user -a "name=<username> [options]"

πŸ”§ Common Examples:

1. βœ… Create a user:

ansible all -m user -a "name=raj"

➑️ Creates user raj with default settings.

2. ❌ Remove a user:

ansible all -m user -a "name=demo state=absent"

➑️ Deletes the user, but keeps home directory by default.

  1. Check User Existence:

ansible all -a "id raj"

πŸ”§ service Module – Purpose

  • Start, stop, restart, reload, enable, or disable services on remote hosts.

πŸ“Œ Syntax:

ansible all -m service -a "name=<service-name> state=<state> [enabled=yes|no]"

πŸ”§ Common Examples:

1. βœ… Start a service (e.g., nginx)

ansible all -m service -a "name=nginx state=started"

2. βœ… Stop a service

ansible all -m service -a "name=nginx state=stopped"

3. πŸ” Restart a service

ansible all -m service -a "name=nginx state=restarted"

4. πŸ”„ Reload service configuration

ansible all -m service -a "name=nginx state=reloaded"

5. πŸš€ Enable service to start on boot

ansible all -m service -a "name=nginx enabled=yes"

6. ❌ Disable auto-start on boot

ansible all -m service -a "name=nginx enabled=no"

🧠 Notes:

PropertyDescription
statestarted, stopped, restarted, reloaded
enabledyes or no (manage auto-start)
Supports bothsysvinit and systemd service managers

πŸ§ͺ Check status of a service:

ansible all -a "systemctl status nginx"

πŸ“¦ apt Module (Debian, Ubuntu)

βœ… Syntax:

ansible all -m apt -a "name=<package-name> state=<present|absent|latest> update_cache=yes"

πŸ”§ Examples:

1. βœ… Install a package (e.g., nginx)

ansible all -m apt -a "name=nginx state=present update_cache=yes"

2. ❌ Remove a package

ansible all -m apt -a "name=nginx state=absent"

3. πŸ”„ Update an existing package to latest version

ansible all -m apt -a "name=nginx state=latest"

4. 🧠 Run full system upgrade

ansible all -m apt -a "upgrade=dist update_cache=yes"

πŸ” yum Module (RHEL, CentOS, Fedora)

βœ… Syntax:

ansible all -m yum -a "name=<package-name> state=<present|absent|latest>"

πŸ”§ Examples:

1. βœ… Install a package

ansible all -m yum -a "name=httpd state=present"

2. ❌ Remove a package

ansible all -m yum -a "name=httpd state=absent"

3. πŸ”„ Update to latest version

ansible all -m yum -a "name=httpd state=latest"

4. 🧠 Update all packages (full system update)

ansible all -m yum -a "name='*' state=latest"

πŸ§ͺ Check package is installed:

ansible all -a "dpkg -l | grep nginx"     # Debian
ansible all -a "rpm -qa | grep httpd"     # RHEL

πŸ“¦ package Module – Purpose

  • Universal package manager wrapper.

  • Works across:

    • apt (Debian/Ubuntu)

    • yum / dnf (RHEL, CentOS, Fedora)

    • zypper (SUSE)

    • pkg (FreeBSD)

  • The package module uses the default package manager of the host OS.

  • For advanced options (like update_cache, upgrade, repo handling), use apt, yum directly.


πŸ“Œ Basic Syntax:

ansible all -m package -a "name=<package-name> state=<present|absent|latest>"

πŸ”§ Common Examples

βœ… 1. Install a package (e.g., curl)

ansible all -m package -a "name=curl state=present"

πŸ” 2. Update package to the latest version

ansible all -m package -a "name=curl state=latest"

❌ 3. Remove a package

ansible all -m package -a "name=curl state=absent"

βœ… 4. Install multiple packages

ansible all -m package -a "name=['htop','curl','git'] state=present"

🧠 Why Use package Instead of apt or yum?

ScenarioUse package
Target hosts have mixed OSβœ…
Writing portable playbooksβœ…
Want simplified logicβœ…
Need OS-specific options❌ (Use apt, yum)

πŸ§ͺ Check if package installed (command module):

ansible all -a "which curl"

WE MADE IT !!

⚠️ Note

1
Subscribe to my newsletter

Read articles from Rajesh Gurajala directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Rajesh Gurajala
Rajesh Gurajala