Cron Otomatis Screenshot Output Terminal Linux

Sebagai seorang sysadmin, salah satu tugas rutin adalah mengirimkan laporan kepada end user. Selama periode waktu tertentu, klien saya hanya meminta laporan penggunaan disk server setiap bulannya. Cukup sederhana, saya langsung buat sebuah skrip Bash yang menjalankan perintah df -h, lalu mengirimkannya lewat email. Berikut adalah contoh script existing yang saya gunakan:

#!/bin/bash

dari="from:admin@excellent.co.id"
tujuan="to:staff@excellent.co.id"
salinan="cc:support@colamen.id,manager@excellent.co.id"
subject="Subject: [REPORT BULANAN]: Penggunaan Disk Server Zimbra Excellent (mail.excellent.co.id.id)"
file_disk="/tmp/disk.txt"
file_status="/tmp/status.txt"
body_email="/tmp/body.txt"
file_report="/tmp/report.txt"

df -h > $file_disk

echo "Hi Team Excellent,

Berikut adalah report penggunaan disk VPS mail.excellent.co.id:

$(cat $file_disk)

Terima Kasih" > $body_email

echo "$dari" > $file_report
echo "$tujuan" >> $file_report
echo "$salinan" >> $file_report
echo "$subject" >> $file_report
echo "$(cat $body_email)" >> $file_report

cat $file_report | /opt/zimbra/common/sbin/sendmail -f $dari -t

Saya define script ini di crontab sistem operasi Linux yang digunakan email server dan akan berjalan secara otomatis tanggal 1 setiap bulannya. Semuanya berjalan lancar, sampai akhirnya end user meminta agar laporan yang dikirimkan tidak hanya berupa teks biasa, melainkan berbentuk gambar atau screenshot dari terminal. Alasannya mungkin agar terlihat sebagai bukti yang valid.

Secara teknis, sebenarnya saya bisa saja SSH ke server setiap bulan lalu menjalankan perintah df -h, lalu mengambil screenshot secara manual. Namun, hal ini akan memakan waktu dan mengganggu alur kerja saya, apalagi saya juga harus compose emailnya secara manual lalu upload screenshotnya, ditambah lagi jika ada beberapa end user dengan request yang sama. Akhirnya, saya mulai mencari cara untuk mengotomatisasi proses ini dan saya menemukan PhantomJS, sebuah headless browser yang bisa mengambil screenshot dari halaman web.

Ternyata prosesnya tidak semudah yang saya bayangkan. Ada beberapa kendala yang harus disesuaikan. Langkah pertama adalah melakukan instalasi PhantomJS.

# cd /srv
# wget -c https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
# tar -xvjf phantomjs-2.1.1-linux-x86_64.tar.bz2
# mv phantomjs-2.1.1-linux-x86_64 /usr/local/share/
# ln -s /usr/local/share/phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/sbin/
# phantomjs -v
2.1.1

Setelah melakukan instalasi PhantomJS saya membuat skrip JavaScript yang akan dijalankan oleh PhantomJS. Skrip PhantomJS akan file yang berisi output dari perintah df -h dan mengubahnya menjadi gambar.

var diskFile = '/tmp/disk.txt';
var dfOutput = fs.read(diskFile);
var page = require('webpage').create();

page.content = '<html><body><pre>' + dfOutput + '</pre></body></html>';
page.render(outputFile, {format: 'png', quality: '100'});

Hasilnya? Gambarnya ada tapi dengan latar belakangnya transparan, saya gamau, saya maunya backgroundnya putih saja supaya real seperti kita screenshot terminal. Solusinya, saya tambahkan sedikit CSS untuk memberikan warna latar belakang putih.

.....
page.content = '<html><head><style>body { background-color: #ffffff; }</style></head><body><pre>' + dfOutput + '</pre></body></html>';
.....

Setelah gambar laporan disk berhasil, end user juga meminta gambar laporan untuk penggunaan CPU & RAM juga. Akhirnya saya menyesuaikan skrip PhantomJS untuk generate dua gambar sekaligus, gambar pertama merupakan penggunaan disk lalu gambar kedua merupakan penggunaan CPU & RAM. Tantangan berikutnya adalah mengirimkan dua attachment dalam satu email menggunakan tools di Linux.

Saya beralih dari sendmail ke mutt karena “katanya” lebih mudah untuk melampirkan file hehe. Namun, ada beberapa kendala lagi:

  • Muncul pesan No configuration file: Ini sebenarnya hanya peringatan, cukup tambahkan 2>/dev/null di akhir perintah mutt untuk ignore pesan ini.
  • Namun, email juga terkirim dari root@hostname.domain.com padahal saya maunya dari admin@excellent.co.id. Meskipun saya sudah mengatur alamat pengirim di mutt, email tetap terkirim dari root@hostname.domain.com karena skrip dijalankan oleh user root di Linux.

Setelah saya explore lagi, sendmail sebenarnya bisa digunakan untuk mengirimkan email dengan multiple attachment, tapi kita harus decode dulu file gambarnya lalu masukan ke header email dalam format base64. Awalnya, saya mencoba tools uuencode untuk mengubah gambar menjadi format base64 agar bisa dilampirkan. Sayangnya, perintah ini tidak terpasang secara default. Jadi, saya ganti dengan perintah bawaan Linux base64 dan hasilnya sesuai harapan.

Setelah melalui beberapa percobaan dan perbaikan, inilah skrip PhantomJS yang akhirnya bisa melakukan generate gambar sesuai dengan harapan saya.

var fs = require('fs');
var diskFile = '/tmp/disk.txt';
var outputFile = '/tmp/disk-usage-report.png';
var cpuramFile = '/tmp/cpu-ram.txt';
var outputCpuramFile = '/tmp/cpu-ram-usage-report.png';
var page = require('webpage').create();
var dfOutput = fs.read(diskFile);
var cpuramOutput = fs.read(cpuramFile);

// Isi konten halaman web dengan output dari df -h
page.content = '<html><head><style>body { background-color: #ffffff; }</style></head><body><pre>' + dfOutput + '</pre></body></html>';
page.render(outputFile, {format: 'png', quality: '100'});

// Isi konten halaman web dengan output dari CPU RAM usage
page.content = '<html><head><style>body { background-color: #ffffff; }</style></head><body><pre>' + cpuramOutput + '</pre></body></html>';
page.render(outputCpuramFile, {format: 'png', quality: '100'});

Setelah itu saya menyesuaikan script bash dengan proses kerja sebagai berikut:

  1. Mengambil output df -h dan mpstat/free -m, lalu menyimpannya ke file teks
  2. Menjalankan skrip PhantomJS untuk membuat gambar dari file-file teks tersebut
  3. Membuat email dengan header dengan isi pesan serta melampirkan gambar yang sudah di-encode dengan base64 lalu memastikan email dikirim dari alamat yang benar admin@excellent.co.id
#!/bin/bash

dari="admin@excellent.co.id" 
tujuan="staff@excellent.co.id" 
salinan="support@colamen.id,manager@excellent.co.id"
subject="[REPORT BULANAN]: Penggunaan Disk, CPU & RAM VPS PLN Icon Plus (mail.excellent.co.id)"
file_disk="/tmp/disk.txt"
file_cpuram="/tmp/cpu-ram.txt"
body_email="/tmp/body.txt"
file_report="/tmp/report.txt"
file_disk_report="/tmp/disk-usage-report.png"
file_cpu_ram_report="/tmp/cpu-ram-usage-report.png"

df -h > $file_disk
mpstat -P ALL > $file_cpuram
free -m >> $file_cpuram

phantomjs /opt/excellent/capture-disk-cpu-ram-usage.js

echo "Hi Team Excellent,

Berikut kami lampirkan capture penggunaan disk, RAM & CPU VPS mail.excellent.co.id.

Apabila ada hal yang kurang jelas mohon informasikan kembali pada kami.

Terima Kasih" > $body_email

# --- Buat Email dengan Lampiran menggunakan uuencode ---
(
# Header email
echo "From: $dari"
echo "To: $tujuan"
echo "Cc: $salinan"
echo "Subject: $subject"
echo "Mime-Version: 1.0"
echo "Content-Type: multipart/mixed; boundary=\"_BOUNDARY\""
echo ""
echo "--_BOUNDARY"
echo "Content-Type: text/plain; charset=\"us-ascii\""
echo ""

# Isi teks email
cat "$body_email"

# Lampiran pertama (Disk Report)
echo "--_BOUNDARY"
echo "Content-Type: image/png"
echo "Content-Transfer-Encoding: base64"
echo "Content-Disposition: attachment; filename=\"$file_disk_report\""
echo ""
base64 "$file_disk_report"
echo ""

# Lampiran kedua (CPU & RAM Report)
echo "--_BOUNDARY"
echo "Content-Type: image/png"
echo "Content-Transfer-Encoding: base64"
echo "Content-Disposition: attachment; filename=\"$file_cpu_ram_report\""
echo ""
base64 "$file_cpu_ram_report"
echo ""

# Tutup email
echo "--_BOUNDARY--"
) | /opt/zimbra/common/sbin/sendmail -t -i -f "$dari"

Saat ini script tersebut sudah saya aktifkan di crontab supaya bisa melakukan generate lalu mengirimkannya ke email secara otomatis setiap bulannya.

Leave a Reply

Your email address will not be published.