Menggunakan perintah ad-hoc Ansible untuk tugas operasional harian: cek uptime, kelola file dan package, restart layanan, hingga push SSH key ke banyak server hanya dalam satu command line.

Setelah di episode 3 sebelumnya kita membahas cara mengelola inventory — mulai dari format INI dan YAML, pengelompokkan host, host patterns, hingga dynamic inventory — pada episode kali ini kita akan mempraktikkan penggunaan inventory tersebut untuk melakukan pekerjaan nyata: Ad-Hoc Commands.
Ad-hoc command adalah mode Ansible yang paling cepat dan ringkas. Kalau kalian tipe orang yang "lebih dulu bertanya daripada menulis", ad-hoc adalah jawabannya: cukup satu baris perintah, dan puluhan server langsung merespons. Dalam operasional harian, momen seperti ini sangat sering terjadi — misalnya jam 2 pagi ada alert server disk penuh, dan kalian hanya perlu mengecek 40 server sekaligus tanpa menulis playbook.
Namun perlu diingat: ad-hoc bukan pengganti playbook. Ia adalah pisau saku — cepat untuk tugas sekali jalan, tapi bukan alat untuk pekerjaan berulang yang harus terdokumentasi. Di akhir episode kita akan melihat kapan harus berpindah ke playbook.
Secara sederhana, ad-hoc command adalah perintah Ansible yang dijalankan langsung dari terminal tanpa file playbook. Ia memanfaatkan inventory yang sudah kalian siapkan di episode 3, lalu mengeksekusi satu module ke host yang ditargetkan.
Important
Kapan ad-hoc digunakan? Saat tugas bersifat sekali jalan, eksploratif, atau menanggapi keadaan darurat — seperti cek disk, restart layanan, atau melihat versi kernel. Tugas yang harus dijalankan berulang dan dikelola bersama tim sebaiknya ditulis sebagai playbook (episode 5).
Struktur dasar perintah ad-hoc adalah:
ansible <host-pattern> -m <module_name> -a "<module_args>"Mari kita bedah tiap bagiannya:
<host-pattern> — target server, persis seperti host pattern yang kita bahas di episode 3 (all, webservers, webservers:&staging, dan seterusnya).-m <module_name> — menentukan modul yang dipakai. Modul adalah "senjata" yang menentukan apa yang dilakukan Ansible di server target.-a "<module_args>" — argumen modul, berisi parameter spesifik sesuai modul yang dipilih.Ada juga flag umum yang akan sangat sering kalian pakai:
| Flag | Fungsi | Contoh |
|---|---|---|
-i / --inventory | Menentukan file inventory (bisa statis atau dinamis) | -i inventory.yml |
-b / --become | Menjalankan dengan privilege escalation (sudo) | -b |
-K / --ask-become-pass | Meminta password sudo secara interaktif | -bK |
-u / --user | Menentukan user SSH yang dipakai | -u deploy |
--check | Dry run — hanya melaporkan, tidak mengubah apa pun | --check |
-v / -vvv | Menambah detail verbosity | -vvv |
Contoh paling sederhana: menguji koneksi ke semua host dalam inventory.
ansible all -i inventory.yml -m ansible.builtin.pingweb-01.prod.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
db-01.prod.example.com | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}Setiap host menjawab pong — artinya koneksi SSH, autentikasi, dan interpreter Python semuanya berfungsi. Perhatikan bahwa output berbentuk JSON, karena ini adalah format standar hasil eksekusi modul Ansible.
Ada sekumpulan modul yang hampir pasti kalian pakai setiap hari. Mari kita bahas satu per satu.
Selain ansible.builtin.ping yang sudah dicoba di atas, modul lain yang wajib dikenal adalah ansible.builtin.setup — modul yang mengumpulkan facts (informasi sistem) dari setiap host.
ansible all -i inventory.yml -m ansible.builtin.setup -a "filter=ansible_distribution*"web-01.prod.example.com | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "Ubuntu",
"ansible_distribution_file_parsed": true,
"ansible_distribution_major_version": "24",
"ansible_distribution_release": "noble",
"ansible_distribution_version": "24.04",
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false
}Tanpa filter, output setup sangat panjang (berisi CPU, RAM, semua interface jaringan, mounts, dan lainnya) — itu normal, karena modul ini mengumpulkan segalanya. Parameter filter membantu mempersempit output saat kalian hanya butuh bagian tertentu.
Tip
Di episode 7 nanti kita akan belajar memanfaatkan facts ini di dalam playbook — misalnya menentukan package manager berdasarkan ansible_os_family, atau membuat konfigurasi yang menyesuaikan jumlah RAM server. Untuk sekarang, cukup familiar dengan cara memanggilnya lewat ad-hoc.
Ini adalah trio modul yang paling sering disalahpahami. Ketiganya untuk mengeksekusi perintah, tetapi dengan cara yang berbeda:
| Aspek | ansible.builtin.command | ansible.builtin.shell | ansible.builtin.raw |
|---|---|---|---|
Fitur shell (pipe, &&, env var, redirection) | ❌ Tidak didukung | ✅ Didukung penuh | ✅ Didukung penuh |
| Butuh Python di host target | ✅ Ya | ✅ Ya | ❌ Tidak — lewat SSH langsung |
| Keamanan (terhindar dari injeksi shell) | ✅ Paling aman | ⚠️ Perlu kehati-hatian | ⚠️ Perlu kehati-hatian |
| Idempotency bawaan | ❌ Tidak | ❌ Tidak | ❌ Tidak |
| Kapan dipakai | Perintah sederhana tanpa fitur shell | Perintah dengan pipe/loop/variabel | Host tanpa Python, perangkat jaringan, recovery |
Contoh nyata ketiganya:
ansible all -i inventory.yml -m ansible.builtin.command -a "uptime"Warning
Modul shell dan raw sangat powerful, tetapi juga sangat mudah salah pakai. Karena mendukung pipe dan variabel shell, ada risiko command injection — terutama jika ada input dinamis. Aturan praktisnya: gunakan command dulu, baru shell jika memang butuh fitur shell, dan jauhi raw kecuali untuk kasus khusus (host tanpa Python atau mode recovery).
Untuk membuat direktori, menyentuh file, atau mengatur permission, gunakan ansible.builtin.file:
ansible all -i inventory.yml -b -m ansible.builtin.file -a "path=/var/www/blog state=directory owner=deploy group=www-data mode=0755"Argumen state menentukan hasil yang diinginkan:
state | Efek |
|---|---|
directory | Membuat direktori beserta parent-nya |
touch | Membuat file kosong jika belum ada |
file / link | File biasa atau symlink |
absent | Menghapus file/direktori |
Untuk mendorong file dari control node ke server target, gunakan ansible.builtin.copy:
ansible all -i inventory.yml -b -m ansible.builtin.copy -a "src=/etc/nginx/sites-available/blog.conf dest=/etc/nginx/sites-available/blog.conf owner=root group=root mode=0644"Skenario ini sangat berguna saat kalian ingin menyebar file konfigurasi yang sama ke banyak server sekaligus.
Memasang, memperbarui, atau menghapus package adalah tugas harian yang paling umum. Modulnya tergantung distro: ansible.builtin.apt untuk Debian/Ubuntu, ansible.builtin.dnf untuk RHEL/Rocky/Alma, dan ansible.builtin.yum untuk RHEL lama.
ansible all -i inventory.yml -b -m ansible.builtin.apt -a "name=nginx state=present update_cache=yes"Nilai state pada modul package:
state | Arti |
|---|---|
present | Pastikan terpasang (install jika belum) — idempoten |
latest | Pasang dan update ke versi terbaru |
absent | Hapus package |
installed / removed | Sinonim lama (deprecated di beberapa versi) |
Tip
Perhatikan update_cache=yes pada contoh apt — ini setara dengan apt update sebelum install. Tanpa itu, package index di server bisa basi dan package tidak ketemu.
Mengelola layanan (start, stop, restart) menggunakan ansible.builtin.systemd_service untuk sistem modern yang memakai systemd:
ansible web -i inventory.yml -b -m ansible.builtin.systemd_service -a "name=nginx state=restarted"Parameter state pada modul service: started, stopped, restarted, reloaded. Parameter enabled: true/false mengontrol apakah layanan menyala otomatis saat boot.
Note
Modul ini bernama systemd_service menggantikan nama lama service dan systemd. Jika kalian menemui tutorial yang memakai -m service, ketahuilah bahwa modul tersebut kini bagian dari ansible.builtin versi lama dan systemd_service adalah penerusnya untuk systemd.
Sekarang mari kita gabungkan semuanya dalam skenario yang benar-benar terjadi di lapangan.
1. Cek uptime seluruh server
Malam hari, tim ops ingin memastikan tidak ada server yang baru saja reboot sendiri:
ansible all -i inventory.yml -m ansible.builtin.command -a "uptime"web-01.prod.example.com | SUCCESS | rc=0 >>
11:24:35 up 42 days, 3:12, 1 user, load average: 0.31, 0.45, 0.52
web-02.prod.example.com | SUCCESS | rc=0 >>
11:24:35 up 3 min, 1 user, load average: 1.10, 1.00, 0.90
db-01.prod.example.com | SUCCESS | rc=0 >>
11:24:35 up 42 days, 3:12, 1 user, load average: 0.10, 0.12, 0.11Perhatikan web-02 baru up 3 menit — sinyal bahwa ada yang tidak beres di server itu. Dengan satu perintah, kalian sudah menemukan anomali yang harus diselidiki. Bandingkan jika harus ssh ke 3 server satu per satu.
2. Reboot serentak
Ketika ada update kernel atau perubahan config yang butuh restart, lakukan rolling reboot. Meskipun bisa pakai command: reboot, ada modul khusus yang lebih baik: ansible.builtin.reboot. Modul ini melakukan reboot, lalu menunggu host kembali online dan SSH siap — sehingga kalian tahu persis kapan aman lanjut ke server berikutnya.
ansible 'webservers:!web-01.prod.example.com' -i inventory.yml -b -m ansible.builtin.rebootweb-02.prod.example.com | CHANGED => {
"changed": true,
"elapsed": 42,
"rebooted": true
}Caution
Untuk production, jangan reboot semua server sekaligus. Pola di atas sengaja mengecualikan satu server (:!web-01) sebagai pilot, lalu lanjut ke sisanya setelah memastikan yang pertama kembali sehat. Konsep ini sejalan dengan strategi serial yang akan dibahas di episode 15.
3. Push SSH key darurat
Ada anggota tim baru yang butuh akses ke semua server sekarang juga. Modul ansible.builtin.authorized_key menyelesaikannya dengan aman — key ditambahkan ke authorized_keys tanpa mengubah file lain:
ansible all -i inventory.yml -b -m ansible.builtin.authorized_key \
-a "user=deploy state=present key='{{ lookup(\"file\", \"/home/budi/.ssh/id_ed25519.pub\") }}'"Tip
Trik di atas menggunakan lookup plugin file untuk membaca isi public key langsung dari control node — kalian tidak perlu copy-paste isi key secara manual yang rawan typo. Perhatikan tanda kutip ganda di dalam -a untuk melindungi kurung kurawal dari shell.
--check (Dry Run)Sebelum menjalankan perintah yang mengubah sistem (seperti install package atau restart service), sangat disarankan mencoba mode --check terlebih dahulu. Mode ini membuat Ansible tidak benar-benar mengubah apa pun di target — ia hanya menghitung dan melaporkan apa yang akan terjadi.
ansible all -i inventory.yml -b -m ansible.builtin.apt -a "name=nginx state=present" --checkweb-01.prod.example.com | SUCCESS => {
"changed": false,
"msg": "OK"
}
db-01.prod.example.com | SUCCESS => {
"changed": true,
"msg": "If state is 'present', package 'nginx' would be installed"
}Perhatikan dua hal:
changed: false — tidak ada yang akan berubah.changed: true dengan pesan "would be installed" — Ansible memberitahu perubahan yang akan terjadi tanpa benar-benar melakukannya.Warning
--check hanya berguna jika modul mendukungnya. Modul apt, file, copy, dan sebagian besar modul stateful mendukungnya dengan baik. Namun modul command dan shell secara default tidak — karena Ansible tidak bisa memprediksi efek perintah shell sembarangan. Jadi jangan heran kalau --check + command tetap "seolah-olah" akan berubah.
| Kesalahan | Gejala | Solusi |
|---|---|---|
Memakai pipe di command | Error `'/bin/sh: 1: | : not found'` atau perintah tidak jalan |
Lupa -b untuk tugas root | Permission denied saat install/restart service | Tambahkan -b (dan -K jika butuh password) |
Argumen -a tidak dikutip | Shell memecah argumen, target menjadi salah | Selalu kutip penuh: -a "name=nginx state=present" |
Mengharapkan idempotency dari command/shell | Perintah dijalankan setiap kali tanpa memeriksa state | Gunakan modul stateful (apt, file, systemd_service) |
Menggunakan command padahal ada modul | Risiko config drift dan hasil tidak konsisten | Cari modul bawaan dulu: ansible-doc -l | grep ... |
Tip
Tidak yakin modul apa yang ada dan parameternya apa? Jalankan ansible-doc <nama_modul> di control node — dokumentasi lengkap dengan contoh muncul langsung di terminal.
Pada episode 4 ini, kita telah belajar bahwa ad-hoc command adalah pisau saku Ansible untuk operasional harian. Kalian kini mengenal sintaks ansible <pattern> -m <module> -a "<args>", menguasai modul favorit seperti ping, setup, file, copy, apt/dnf, systemd_service, dan memahami kapan harus memakai command, shell, atau raw. Kita juga sudah mempraktikkan skenario nyata — cek uptime, reboot serentak, dan push SSH key darurat — plus mode --check sebagai sabuk pengaman.
Namun ada satu keterbatasan mendasar dari ad-hoc: ia tidak terdokumentasi dan tidak otomatis idempoten. Perintah yang kalian jalankan jam 2 pagi tidak bisa diulang dengan mudah oleh rekan tim lain.
Di episode 5 selanjutnya, kita akan mengatasi keterbatasan ini dengan mempelajari Penulisan Playbook Pertama & Structure Playbook — mengubah perintah-perintah ad-hoc menjadi file YAML yang dapat dijalankan berulang kali, didokumentasikan, dan menghasilkan status OK, CHANGED, hingga FAILED yang bisa dibaca siapa saja. Pastikan tetap semangat!