Dashboard di studi kasus Bab 19.4 sudah bisa menampilkan status server secara langsung dan mencatat setiap anomali lewat fungsi log() ke sebuah file. Tapi cara kerja itu masih pasif: entri [WARN] cuma menunggu di dalam file log sampai ada Sysadmin yang kebetulan membuka dashboard atau menjalankan tail -f. Kalau kejadian itu muncul jam tiga pagi saat semua orang tidur, disk penuh atau service mati bisa dibiarkan berjam-jam sebelum ada yang sadar. Bab ini mengubah pola pasif itu jadi aktif lewat dua konsep yang saling melengkapi: alerting, mekanisme mendeteksi kondisi yang perlu perhatian dan memutuskan kapan sebuah peringatan layak dikirim, serta notifikasi, cara pesan itu sampai ke tangan orang yang tepat lewat saluran komunikasi yang benar-benar mereka pantau. Empat sub-bab berikut membahas tiga saluran notifikasi paling umum dipakai Sysadmin, yaitu email lewat mail/sendmail/SMTP, webhook generik yang jadi format dasar hampir semua integrasi modern, serta Telegram Bot API dan Slack Incoming Webhook yang populer karena pesannya langsung muncul di ponsel. Studi kasus penutup menyambungkan semuanya ke pemeriksaan disk dan service dari Bab 19.3 jadi satu sistem alert otomatis yang siap dijadwalkan.
| Saluran | Kelebihan | Kekurangan |
|---|---|---|
| Hampir semua server sudah bisa kirim tanpa integrasi tambahan, cocok untuk laporan yang agak panjang | Sering terlambat dibaca, rawan masuk folder spam | |
| Webhook generik | Fleksibel, bisa disambungkan ke hampir semua tool monitoring atau automasi | Butuh endpoint penerima yang sudah siap menerima payload |
| Telegram/Slack | Notifikasi instan, langsung muncul di ponsel atau desktop tim | Bergantung pada layanan pihak ketiga tetap online |
20.1 Notifikasi via Email
Email tetap jadi saluran alert paling umum karena hampir setiap server sudah punya jalur pengiriman email bawaan, tanpa perlu mendaftar layanan pihak ketiga baru. Tiga sub-bab berikut membahas tiga cara mengirimnya, dari yang paling sederhana sampai yang paling langsung ke server SMTP.
20.1.1 MTA, MUA, dan Alur Pengiriman Email
Dua istilah ini penting dipahami lebih dulu supaya troubleshooting email yang gagal terkirim tidak menebak-nebak. MUA (Mail User Agent) adalah program yang dipakai untuk menyusun pesan, dalam konteks script berarti perintah seperti mail atau sendmail. MTA (Mail Transfer Agent), seperti Postfix, Exim, atau Sendmail asli, adalah service yang benar-benar bertugas merutekan dan mengantarkan pesan itu ke tujuan lewat jaringan, baik langsung ke internet maupun lewat smarthost penyedia SMTP pihak ketiga. Saat sebuah script memanggil mail atau sendmail, perintah itu sebenarnya cuma menyerahkan pesan ke MTA lokal yang sudah berjalan di server, bukan langsung mengirimkannya sendiri ke internet. Kalau MTA belum terpasang atau belum dikonfigurasi untuk relay keluar, perintah mail bisa saja tetap mengembalikan exit status 0 seolah berhasil, padahal pesannya cuma nyangkut di antrean lokal dan tidak pernah sampai. mailq (atau postqueue -p khusus Postfix) menampilkan isi antrean itu, jadi jadi tempat pertama yang dicek kalau alert "berhasil dikirim" tapi tidak pernah muncul di inbox.
20.1.2 Kirim Cepat dengan mail/mailx
Untuk alert singkat satu baris, perintah mail (sering juga tersedia sebagai mailx) sudah cukup tanpa perlu menyusun header manual. Nama package penyedianya berbeda antar distro: Debian/Ubuntu memakai mailutils (implementasi GNU Mailutils) atau alternatif bsd-mailx, sedangkan RHEL/Fedora/Rocky Linux versi 9 ke atas sudah memakai s-nail sebagai pengganti mailx lama. Pasang salah satunya sesuai distro sebelum lanjut.
sudo apt install mailutils # Debian/Ubuntu
sudo dnf install s-nail # RHEL/Fedora/Rocky Linux 9+echo "Disk root sudah 92% penuh" | mail -s "[ALERT] Disk Penuh - $(hostname)" [email protected]Opsi -s mengisi subjek dan konsisten tersedia di semua implementasi di atas, sedangkan isi pesan diambil dari stdin lewat pipe. Opsi untuk lampiran file berbeda-beda antar implementasi (ada yang memakai -a, ada yang -A), jadi cek dulu lewat man mail di server yang bersangkutan sebelum mengandalkannya; untuk kebutuhan alert sederhana di bab ini, lampiran file sengaja tidak dipakai karena isi pesan cukup berupa teks singkat.
20.1.3 Format Header Manual lewat sendmail -t
sendmail adalah nama command kompatibel yang disediakan hampir semua MTA modern (Postfix, Exim, dan Sendmail asli sendiri), biasanya terpasang di /usr/sbin/sendmail. Tanpa opsi tambahan, penerima harus disebutkan lewat argumen baris perintah; opsi -t membuatnya mengambil daftar penerima dari header To:, Cc:, dan Bcc: yang ditulis langsung di dalam pesan lewat stdin, dengan header Bcc: otomatis dibuang sebelum pesan benar-benar dikirim supaya penerima lain tidak ikut melihatnya. Header Subject: sendiri selalu terbaca sebagai bagian dari pesan terlepas dari opsi -t, yang dipengaruhi opsi ini murni cuma soal dari mana daftar penerima diambil. Kombinasi ini membuat satu pesan lengkap, header dan body sekaligus, bisa disusun dalam satu perintah lewat printf tanpa perlu menuliskan alamat penerima dua kali.
printf 'To: [email protected]\nSubject: [ALERT] Service Down - %s\n\n%s\n' "$(hostname)" "$PESAN" | sendmail -tBaris kosong di antara header dan body (hasil dari \n\n di tengah format printf) wajib ada, persis mengikuti format pesan email standar; tanpa baris kosong itu, sebagian MTA akan menganggap seluruh isi body sebagai bagian dari header dan gagal memprosesnya.
20.1.4 SMTP Langsung Tanpa MTA Lokal
Kadang server tidak punya MTA penuh terpasang, misalnya di dalam container minimal, tapi tetap perlu mengirim alert. msmtp, klien SMTP ringan yang dirancang sebagai pengganti sendmail, jadi pilihan yang lebih ringan dibanding memasang Postfix lengkap. Konfigurasinya disimpan di ~/.msmtprc, dan karena berisi kredensial, permission-nya wajib dibatasi cuma bisa dibaca pemiliknya sendiri.
cat > ~/.msmtprc <<'EOF'
defaults
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
account alert
host smtp.example.com
port 587
auth on
user [email protected]
password isi_password_atau_app_password
from [email protected]
account default : alert
EOF
chmod 600 ~/.msmtprcprintf 'To: [email protected]\nSubject: [ALERT] Disk Penuh\n\nDisk root sudah 92%%.\n' | msmtp [email protected]Kalau msmtp pun tidak ingin dipasang, curl sendiri sudah mendukung protokol SMTP/SMTPS bawaan, cukup dengan mengunggah isi pesan sebagai file (atau lewat stdin dengan tanda -) ke server SMTP tujuan.
printf 'From: [email protected]\nTo: [email protected]\nSubject: [ALERT] Disk Penuh\n\nDisk root sudah 92%%.\n' | curl --ssl-reqd "smtp://smtp.example.com:587" \
--mail-from "[email protected]" \
--mail-rcpt "[email protected]" \
--user "[email protected]:$SMTP_PASSWORD" \
--upload-file ---mail-from dan --mail-rcpt menentukan pengirim dan penerima di level protokol SMTP, --upload-file - membaca isi pesan lengkap dari stdin, dan --ssl-reqd mewajibkan koneksi di-upgrade ke TLS (STARTTLS) di port 587; untuk server yang memakai port 465, ganti skema jadi smtps:// yang sudah terenkripsi sejak awal koneksi tanpa perlu --ssl-reqd. Menaruh $SMTP_PASSWORD polos di dalam script jelas bukan kebiasaan aman; 20.4.3 membahas cara menyimpan kredensial semacam ini di file terpisah yang permission-nya dibatasi.
20.2 Webhook Generik untuk Alert
Sub-bab ini membahas pola integrasi paling fleksibel: mengirim data lewat HTTP POST ke sebuah endpoint, format yang dipahami hampir semua tool monitoring, automasi, dan platform kolaborasi modern.
20.2.1 Konsep Webhook untuk Alert
Webhook adalah endpoint HTTP yang disediakan sebuah layanan untuk menerima notifikasi push dari sistem lain begitu sebuah kejadian terjadi, kebalikan dari API biasa yang harus ditanya berulang-ulang lewat polling. Script cukup mengirim satu request POST berisi payload JSON saat kondisi bermasalah terdeteksi, tanpa layanan tujuan perlu terus-menerus bertanya "ada yang baru?". Banyak platform manajemen insiden (PagerDuty, Opsgenie), tool automasi (n8n, Zapier, Make), maupun sistem custom milik tim sendiri menyediakan endpoint webhook generik yang menerima payload dengan format serupa: satu objek JSON berisi status, sumber alert, dan pesan.
20.2.2 POST Payload JSON dengan curl
curl -X POST "https://webhook.example.com/alert" \
-H "Content-Type: application/json" \
-d '{"status":"critical","host":"web01","message":"Disk root 92% penuh"}'-X POST menegaskan metode HTTP yang dipakai, -H menambahkan header supaya endpoint tahu isi body-nya adalah JSON, dan -d mengirim data itu sebagai body request.
20.2.3 Escaping Aman dengan jq
Menyusun JSON dengan menyambung string secara manual seperti contoh di atas gampang rusak begitu variabel yang disisipkan mengandung tanda kutip ganda, baris baru, atau karakter Unicode, apalagi kalau isi pesan itu sebagian berasal dari output log yang tidak sepenuhnya bisa dikontrol. Kalau isi variabel itu kebetulan bisa dipengaruhi pihak luar (misalnya nama file mencurigakan yang ikut tercatat di log dan disisipkan mentah-mentah ke pesan alert), Attacker berpotensi merusak struktur JSON atau menyisipkan field tambahan yang tidak diinginkan. jq -n (mode null input, membangun output dari nol tanpa perlu input JSON yang sudah ada) bersama opsi --arg jadi cara aman menyusun payload karena setiap value otomatis di-escape sesuai aturan JSON.
PAYLOAD=$(jq -n \
--arg host "$(hostname)" \
--arg pesan "$PESAN" \
'{status: "critical", host: $host, message: $pesan}')
curl -X POST "https://webhook.example.com/alert" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"--arg host "$(hostname)" mendaftarkan variabel bernama $host di dalam filter jq dengan isi dari sisi shell, lalu filter '{status: ..., host: $host, ...}' memakainya sebagai value string yang sudah pasti valid secara JSON, apa pun karakter aneh yang ada di dalamnya.
20.2.4 Retry dan Validasi Response
Script alert yang tidak memeriksa hasil pengirimannya sendiri gampang gagal diam-diam, persis masalah yang sudah dibahas soal job terjadwal di Bab 19.2. curl punya beberapa opsi bawaan untuk menangani ini tanpa perlu logika tambahan yang rumit.
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' \
--retry 3 --retry-delay 2 --max-time 10 \
-X POST "https://webhook.example.com/alert" \
-H "Content-Type: application/json" \
-d "$PAYLOAD")
if [[ "$HTTP_CODE" -ge 200 && "$HTTP_CODE" -lt 300 ]]; then
echo "Notifikasi terkirim"
else
echo "Gagal kirim notifikasi, HTTP $HTTP_CODE" >&2
fi-s menekan progress bar, -o /dev/null membuang body response karena yang dibutuhkan cuma kode statusnya, dan -w '%{http_code}' mencetak kode status HTTP itu saja ke stdout. --retry 3 membuat curl otomatis mengulang sampai 3 kali khusus untuk error yang sifatnya sementara, seperti timeout atau kode HTTP 408/429/5xx, dengan jeda antar percobaan diatur lewat --retry-delay. --max-time 10 membatasi total waktu tunggu satu request supaya script alert sendiri tidak ikut menggantung tanpa batas kalau endpoint tujuan sedang lambat merespons.
20.3 Telegram Bot dan Slack Webhook
Dua platform ini populer untuk alert karena pesannya langsung muncul sebagai notifikasi ponsel, jauh lebih cepat diperhatikan dibanding email yang baru dibuka sesekali.
20.3.1 Bot Telegram dan Chat ID
Bot Telegram dibuat lewat @BotFather, bot resmi Telegram sendiri: kirim perintah /newbot lalu ikuti instruksinya untuk memberi nama, hasil akhirnya berupa token berformat angka:huruf-angka yang jadi kunci autentikasi bot itu. Perlakukan token ini persis seperti password, siapa pun yang memegangnya bisa mengendalikan bot itu sepenuhnya. Selain token, notifikasi butuh chat ID tujuan; cara paling praktis mendapatkannya adalah mengirim pesan apa saja ke bot itu lebih dulu, lalu memanggil method getUpdates lewat curl untuk melihat isi chat.id di response JSON-nya.
curl "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/getUpdates"20.3.2 Kirim Pesan lewat sendMessage
Method sendMessage pada Telegram Bot API cuma butuh dua parameter wajib: chat_id tujuan dan text isi pesan, dikirim lewat endpoint yang menyertakan token bot langsung di URL-nya.
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d text="[ALERT] Disk root $(hostname) sudah 92% penuh" \
-d parse_mode="HTML" > /dev/nullParameter parse_mode bersifat opsional, mengizinkan format teks sederhana seperti tebal atau miring lewat tag HTML dasar (atau sintaks Markdown/MarkdownV2) di dalam isi text. Opsi -d pada curl mengirim data sebagai application/x-www-form-urlencoded, salah satu dari empat format yang didukung endpoint Bot API selain JSON, query string URL, dan multipart/form-data.
Setiap method Bot API, termasuk sendMessage, selalu membalas dengan objek JSON yang punya field ok: bernilai true kalau berhasil, atau false disertai field description berisi alasan gagalnya kalau tidak. Cukup salurkan hasil curl ke jq -r '.ok, .description' (Bab 11 pola pattern-action awk bisa dipakai serupa, tapi jq lebih pas untuk JSON) kalau script perlu tahu otomatis apakah pengiriman benar-benar berhasil. Satu jebakan yang paling sering ditemui di lapangan saat pertama kali menyambungkan bot ke alert: Telegram tidak mengizinkan bot mengirim pesan duluan ke user yang belum pernah memulai percakapan dengannya, kebijakan privasi bawaan platform. Kalau chat_id sudah benar tapi respons balik justru {"ok":false,...,"description":"Forbidden: bot can't initiate conversation with a user"}, penyebabnya bukan bug di script, melainkan akun tujuan belum pernah menekan Start atau mengirim pesan apa pun ke bot itu lebih dulu.
20.3.3 Membuat Slack Incoming Webhook
Slack Incoming Webhook dibuat lewat dashboard Slack App: buat App baru di halaman pengembang Slack, pilih workspace tujuan, aktifkan fitur Incoming Webhooks, lalu klik "Add New Webhook to Workspace" dan pilih channel yang akan menerima pesan. Hasilnya berupa satu URL unik berformat https://hooks.slack.com/services/T000.../B000.../xxxx.... URL ini bersifat self-authenticating, artinya siapa pun yang memegangnya bisa langsung mengirim pesan ke channel yang dipilih tanpa autentikasi tambahan, jadi perlakukan sama seperti password dan jangan pernah ikut ter-commit ke repository publik.
20.3.4 Kirim Pesan ke Slack
PAYLOAD=$(jq -n --arg teks "[ALERT] Disk root $(hostname) sudah 92% penuh" '{text: $teks}')
curl -X POST "$SLACK_WEBHOOK_URL" -H "Content-Type: application/json" -d "$PAYLOAD"Payload minimal yang dibutuhkan cuma satu field, text, isinya persis seperti pesan yang ingin ditampilkan di channel tersebut. Pola membangun payload lewat jq -n --arg ini sengaja dipakai lagi persis seperti 20.2.3, karena isi pesan alert sama-sama berasal dari variabel yang bisa mengandung karakter yang merusak JSON kalau disambung manual.
Request yang berhasil dibalas Slack dengan kode HTTP 200 dan body berupa teks polos ok, bukan JSON. Request yang gagal membalas dengan kode 400 beserta pesan singkat penyebabnya di body, misalnya invalid_payload kalau JSON yang dikirim tidak valid, channel_not_found kalau channel tujuan sudah dihapus, atau no_service kalau URL webhook-nya sudah dicabut lewat halaman pengaturan App. Pola pengecekan lewat HTTP_CODE di 20.2.4 berlaku persis sama untuk memvalidasi pengiriman ke Slack, tinggal mengganti URL tujuannya jadi $SLACK_WEBHOOK_URL.
20.4 Studi Kasus: Alert Otomatis Service Down/Disk Penuh
Studi kasus penutup ini menyambungkan pemeriksaan cek_disk dan cek_service dari Bab 19.3 dengan tiga saluran notifikasi yang baru dibahas, jadi satu script alert-notifikasi.sh yang siap dijadwalkan lewat cron.
20.4.1 Rancangan Dispatcher Notifikasi
Kredensial (token bot, URL webhook, alamat email tujuan) disimpan di file konfigurasi terpisah, alert-notifikasi.env, bukan ditulis langsung di dalam script. Fungsi kirim_alert() bertindak sebagai dispatcher: menerima satu pesan, lalu meneruskannya ke setiap fungsi pengirim (kirim_telegram, kirim_slack, kirim_email) yang masing-masing memeriksa dulu apakah variabel kredensialnya terisi sebelum benar-benar mengirim. Pola ini membuat Sysadmin bebas mengaktifkan satu saluran saja atau semuanya sekaligus cukup dengan mengisi atau mengosongkan file konfigurasi, tanpa perlu mengubah isi script.
20.4.2 Implementasi alert-notifikasi.sh
Buat dulu file konfigurasi kredensialnya, lalu batasi permission-nya persis seperti ~/.msmtprc di 20.1.4.
TELEGRAM_BOT_TOKEN="123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ"
TELEGRAM_CHAT_ID="987654321"
SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T000/B000/xxxxxxxxxxxxxxxxxxxxxxxx"
EMAIL_TUJUAN="[email protected]"chmod 600 alert-notifikasi.env#!/bin/bash
set -uo pipefail
DIR_SCRIPT=$(dirname "$(readlink -f "$0")")
source "$DIR_SCRIPT/alert-notifikasi.env"
SERVICES=("nginx" "cron")
LOG_FILE="alert-notifikasi.log"
STATE_DIR="/tmp/alert-notifikasi-state"
COOLDOWN_DETIK=1800
mkdir -p "$STATE_DIR"
log() {
local level="$1"
shift
local waktu
waktu=$(date '+%Y-%m-%d %H:%M:%S')
printf '[%s] [%s] %s\n' "$waktu" "$level" "$*" >> "$LOG_FILE"
}
kirim_telegram() {
local pesan="$1"
[[ -z "${TELEGRAM_BOT_TOKEN:-}" ]] && return 0
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
--data-urlencode "text=$pesan" > /dev/null
}
kirim_slack() {
local pesan="$1"
[[ -z "${SLACK_WEBHOOK_URL:-}" ]] && return 0
local payload
payload=$(jq -n --arg teks "$pesan" '{text: $teks}')
curl -s -X POST "$SLACK_WEBHOOK_URL" -H "Content-Type: application/json" -d "$payload" > /dev/null
}
kirim_email() {
local pesan="$1"
[[ -z "${EMAIL_TUJUAN:-}" ]] && return 0
echo "$pesan" | mail -s "[ALERT] $(hostname)" "$EMAIL_TUJUAN"
}
sudah_cooldown() {
local kunci="$1"
local file_state="$STATE_DIR/$kunci"
local sekarang
sekarang=$(date +%s)
if [[ -f "$file_state" ]]; then
local terakhir
terakhir=$(cat "$file_state")
(( sekarang - terakhir < COOLDOWN_DETIK )) && return 1
fi
echo "$sekarang" > "$file_state"
return 0
}
kirim_alert() {
local kunci="$1"
local pesan="$2"
log WARN "$pesan"
if sudah_cooldown "$kunci"; then
kirim_telegram "$pesan"
kirim_slack "$pesan"
kirim_email "$pesan"
else
log INFO "Alert '$kunci' masih dalam cooldown, notifikasi dilewati"
fi
}
cek_disk() {
local persen
persen=$(df -h / --output=pcent | tail -n 1 | tr -d ' %')
if (( persen >= 80 )); then
kirim_alert "disk_root" "Disk root $(hostname) sudah ${persen}% penuh"
fi
}
cek_service() {
local svc
for svc in "${SERVICES[@]}"; do
if ! systemctl is-active --quiet "$svc"; then
kirim_alert "service_$svc" "Service $svc di $(hostname) tidak aktif"
fi
done
}
cek_disk
cek_serviceDIR_SCRIPT memakai readlink -f "$0" untuk mendapatkan path absolut script ini sendiri, apa pun direktori kerja saat script dipanggil, supaya alert-notifikasi.env selalu ditemukan di folder yang sama meski dipanggil lewat path relatif dari cron. Tiap fungsi kirim_* mengecek dulu variabelnya lewat [[ -z "${VAR:-}" ]] (Bab 6.2), memakai ${VAR:-} supaya tidak error kalau variabelnya memang belum pernah diisi sama sekali di file konfigurasi. kirim_telegram sengaja memakai --data-urlencode, bukan -d polos seperti di 20.3.2, karena opsi ini otomatis meng-encode karakter khusus di dalam $pesan sesuai aturan URL, jadi lebih aman untuk isi pesan yang datanya sepenuhnya dinamis. set -uo pipefail di baris awal mengaktifkan sebagian mode debug yang dibahas tuntas di Bab 25.1; -e sengaja tidak diikutkan di sini karena kalau cek_disk gagal di tengah jalan, cek_service di bawahnya tetap harus sempat berjalan, bukan ikut membatalkan seluruh script.
20.4.3 Cooldown: Mencegah Alert Spam
Kalau script ini dijadwalkan berjalan tiap 5 menit lewat cron dan kondisi disk penuh ternyata berlangsung selama satu jam, tanpa mekanisme tambahan Sysadmin bisa kebanjiran 12 notifikasi identik di channel yang sama, salah satu jebakan yang paling sering ditemui di lapangan saat pertama kali menyambungkan monitoring ke notifikasi. Fungsi sudah_cooldown() menyimpan timestamp pengiriman terakhir untuk tiap jenis alert (dibedakan lewat kunci, misalnya disk_root atau service_nginx) di sebuah file kecil di STATE_DIR. Selama selisih waktu sekarang dengan timestamp itu masih di bawah COOLDOWN_DETIK (1800 detik atau 30 menit pada contoh di atas), pengiriman notifikasi dilewati meski kondisinya tetap dicatat ke log lewat log WARN. Angka COOLDOWN_DETIK ini bukan aturan baku, melainkan trade-off yang perlu disesuaikan sendiri: terlalu pendek membuat notifikasi tetap berulang mengganggu, terlalu panjang berisiko alert kedua yang sebenarnya beda kejadian (misalnya disk penuh lagi setelah sempat lega) ikut tertahan.
20.4.4 Verifikasi dan Penjadwalan
Beri izin eksekusi pada kedua file, lalu jalankan manual dulu untuk memastikan tidak ada error sebelum dijadwalkan.
chmod +x alert-notifikasi.sh
chmod 600 alert-notifikasi.env
./alert-notifikasi.sh
tail -f alert-notifikasi.logUji skenario "bermasalah" secara sengaja, misalnya menghentikan sementara salah satu service yang terdaftar di SERVICES (ingat mengaktifkannya lagi setelah selesai menguji, persis pengingat yang sama seperti Bab 19.4.3), lalu pastikan notifikasi benar-benar muncul di Telegram, Slack, atau inbox email yang dikonfigurasi, bukan cuma tercatat di file log. Setelah yakin berjalan benar, jadwalkan lewat crontab -e mengikuti pola Bab 18.1, dengan path absolut supaya cron tidak salah mencari file konfigurasi maupun script-nya sendiri.
*/5 * * * * /path/lengkap/ke/alert-notifikasi.shSistem alert yang baru dibangun di bab ini melengkapi fondasi logging dan monitoring dari Bab 19: kondisi bermasalah kini tidak cuma tercatat, tapi juga aktif memberi tahu. Bab 21 melanjutkan ke sisi lain administrasi server, yaitu backup otomatis, transfer file aman, dan deployment; fungsi kirim_alert() yang sama bisa langsung dipakai ulang di sana untuk memberi tahu Sysadmin kalau proses backup atau deploy ternyata gagal di tengah jalan.

