Sistem Linux yang tidak pernah dirawat tidak rusak mendadak — ia melambat pelan-pelan. Cache aplikasi menumpuk tanpa pernah dibersihkan, log terkompresi berbaris berbulan-bulan, sisa instalasi tertinggal di folder tmp, paket update menunggu jendela maintenance yang tak pernah datang, dan suatu pagi partisi data terisi 89% tanpa peringatan. Tidak satu pun dari gejala itu terasa mendesak hari ini, tetapi bersama-sama mereka memakan ruang dan menumpuk risiko. Proyek ini merangkai pekerjaan perawatan yang biasanya dikerjakan manual menjadi satu skrip bash: memeriksa kondisi sistem, membersihkan file lama dengan aturan yang ketat, lalu menutup setiap eksekusi dengan laporan yang bisa dibaca manusia.
Skrip yang kita bangun bekerja dalam satu eksekusi:
- memeriksa tiga hal dari snapshot data yang bisa dibekukan: pemakaian disk dari output
df, paket update tertunda dari output simulasiapt-get -s upgrade, dan service gagal dari daftar state, - membersihkan file cache, log terkompresi (
*.gz), dan file tmp usang — hanya di dalam folder whitelist yang tercantum di berkas konfigurasi, dengan umur minimum per jenis, - berjalan dalam mode dry-run secara default: daftar kandidat penghapusan ditampilkan lebih dulu, dan tidak ada satu file pun terhapus sebelum
--applydiketik sendiri — mode juga sengaja tidak bisa diubah dari berkas konfigurasi, - menulis laporan terstruktur — apa yang dicek, apa yang dibersihkan, berapa ruang yang dihemat, dan apa yang perlu ditindaklanjuti — ke stdout sekaligus berkas laporan,
- menerima tanggal acuan lewat variabel
HARI_INIsehingga seluruh perhitungan umur file deterministik dan bisa diuji otomatis.
Tampilan Program Akhir #
Sesi berikut menunjukkan hasil akhir proyek pada data contoh server-kantor yang tanggal acuannya dikunci ke 2026-02-15 supaya outputnya bisa dibandingkan ulang. Eksekusi pertama adalah dry-run — mode default — dan eksekusi kedua dengan --apply benar-benar menghapus. Perhatikan bahwa setelah apply, file yang masih segar tetap utuh:
$ HARI_INI=2026-02-15 bash pemeliharaan.sh
================================================================
LAPORAN PEMELIHARAAN SISTEM
Tanggal acuan : 2026-02-15
Mode : DRY-RUN (tidak ada file yang dihapus)
================================================================
PEMERIKSAAN
----------------------------------------------------------------
1. Pemakaian disk (ambang 80%)
/ 73% OK
/data 89% WASPADA
/dev/shm 1% OK
2. Paket update tertunda
4 paket siap di-upgrade: curl, libcurl4, libssl3, openssl
3. Service gagal
2 service failed: nginx.service, postgresql.service
PEMBERSIHAN
----------------------------------------------------------------
cache — file lebih tua dari 2026-01-16 (whitelist: data/cache)
[dry-run] data/cache/lama.txt (15 byte)
log — file *.gz lebih tua dari 2026-02-01 (whitelist: data/log)
[dry-run] data/log/app.log.1.gz (25 byte)
tmp — file lebih tua dari 2026-02-08 (whitelist: data/tmp)
[dry-run] data/tmp/sisa.tmp (20 byte)
HEMAT RUANG
----------------------------------------------------------------
Total: 3 file, 60 byte (potensi hemat; jalankan --apply untuk benar-benar menghapus)
REKOMENDASI
----------------------------------------------------------------
1. Pemakaian disk melewati ambang 80% di /data:
cari penyumbang terbesar dengan du -h, lalu bersihkan atau pindahkan.
2. Ada 4 paket update tertunda:
jalankan apt upgrade pada jadwal maintenance berikutnya.
3. Ada 2 service gagal (nginx.service, postgresql.service):
periksa journalctl -u <unit> untuk penyebabnya, lalu restart bila aman.
4. DRY-RUN menemukan 3 file (60 byte) layak dibersihkan:
periksa daftar di bagian PEMBERSIHAN, lalu jalankan ulang dengan --apply.
$ HARI_INI=2026-02-15 bash pemeliharaan.sh --apply | grep -E 'terhapus|^Total'
[terhapus] data/cache/lama.txt (15 byte)
[terhapus] data/log/app.log.1.gz (25 byte)
[terhapus] data/tmp/sisa.tmp (20 byte)
Total: 3 file, 60 byte (benar-benar dibebaskan dari disk)
$ ls -1 data/cache data/log data/tmp
data/cache:
baru.txt
data/log:
app.log
app.log.2.gz
data/tmp:
aktif.tmp
Tampilannya panjang, tetapi setiap barisnya adalah keputusan desain: tiga temuan pemeriksaan dengan status OK atau WASPADA, kandidat pembersihan yang dibatasi whitelist dan umur, total ruang dalam byte, dan rekomendasi yang berubah mengikuti temuan — termasuk saran menjalankan --apply yang hanya muncul saat dry-run. Setelah apply, baru.txt, app.log (log lama yang bukan *.gz), app.log.2.gz, dan aktif.tmp tetap ada: pembersihan menunjuk file yang tepat, bukan folder sebelahnya.
Tujuan Pembelajaran #
Setelah menyelesaikan proyek ini, kita mampu:
- memisahkan pengumpulan data dari analisis lewat pola snapshot — output
df,apt-get -s upgrade, dan daftar service dibekukan dulu agar hasilnya bisa diulang dan diuji, - memparsing output
dfdengan awk: mengambil kolom persentase, membuang tanda%, dan membandingkannya dengan ambang, - menghitung paket tertunda dan service gagal dari fixture dengan pola awk yang tahan format,
- menerapkan pembersihan ber-whitelist: umur file lewat
find ! -newermt, pola nama*.gzuntuk log, danfind -deleteyang hanya berangkat dari folder whitelist, - mendesain keamanan sebagai default: dry-run adalah mode bawaan, mode tidak bisa diubah dari konfigurasi, dan setiap penghapusan tercatat ukurannya,
- menyusun laporan terstruktur dengan seksi tetap dan rekomendasi yang diturunkan dari temuan,
- membuktikan seluruh janji lewat test suite bash: parsing benar, dry-run tidak menghapus, apply hanya menghapus yang benar, laporan akurat, exit code sesuai kontrak.
Prasyarat #
Proyek ini merangkai kembali alat yang sudah dikenal, tanpa memperkenalkan tool baru. Chapter yang paling sering dirujuk:
- Functions
— memecah skrip menjadi fungsi seperti
bersihkan()dengan argumen, - Backup Strategies — kerangka retensi yang juga melatari keputusan umur file: berapa lama sesuatu disimpan sebelum dianggap usang,
- Disk Monitoring
— membaca output
dfdan ambang pemakaian disk.
Tahapan Pengerjaan #
Proyek dikerjakan dalam tiga bagian berurutan. Setiap bagian diakhiri dengan keadaan yang bisa dijalankan dan diamati:
- Bagian 1: Pemeriksaan Sistem — membangun snapshot data beku lalu memeriksa disk, paket tertunda, dan service gagal dari situ.
- Bagian 2: Pembersihan File — menerapkan tiga pengaman (whitelist, umur, dry-run) sebelum satu file pun dihapus.
- Bagian 3: Laporan Pemeliharaan — merangkai pemeriksaan dan pembersihan menjadi skrip final yang menghasilkan laporan, lalu membuktikannya lewat test suite.
Mulailah dari Bagian 1 karena snapshot dan parsing yang dibangun di sana menjadi masukan langsung untuk laporan di dua bagian berikutnya. Berkas sumber proyek (pemeliharaan.sh, pemeliharaan.conf, dan run-tests.sh) tersedia pada bagian Berkas Sumber di bawah halaman setiap bagian, sehingga Anda bisa membandingkan hasil pekerjaan dengan versi referensi kapan saja.
Periksa disk, paket tertunda, dan service gagal sebagai dasar pemeliharaan.
Buka → # Bagian 2: Pembersihan FileBersihkan cache, log lama, dan file sisa dengan aturan aman yang dikonfigurasi.
Buka → # Bagian 3: Laporan PemeliharaanSusun laporan pemeliharaan terstruktur yang mudah dipindai administrator.
Buka →Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
src/pemeliharaan.sh
Unduh berkas#!/usr/bin/env bash
# pemeliharaan.sh — pemeliharaan berkala: periksa, bersihkan, laporkan.
#
# Membaca snapshot data sistem (df.txt, paket.txt, services.txt) dari
# folder data, memeriksa tiga hal — pemakaian disk, paket update
# tertunda, service gagal — lalu membersihkan file cache, log terkompresi
# (*.gz), dan file tmp usang HANYA di dalam folder whitelist yang
# tercantum di berkas konfigurasi. Mode default DRY-RUN: tidak ada
# file yang dihapus sampai --apply diberikan, dan mode tidak bisa
# diubah dari konfigurasi. Hasil akhirnya adalah laporan terstruktur
# yang ditulis ke stdout sekaligus berkas laporan.
#
# Pemakaian:
# bash pemeliharaan.sh [--data-dir DIR] [--config FILE] [--apply]
#
# Variabel lingkungan (berguna untuk pengujian):
# CONF berkas konfigurasi yang dibaca (default: pemeliharaan.conf)
# SOURCE_DIR folder data; kalah oleh --data-dir (default: data)
# HARI_INI tanggal acuan umur file, format YYYY-MM-DD (default: hari ini)
#
# Kode keluar:
# 0 sukses 1 konfigurasi tidak valid
# 2 berkas snapshot tidak ada 3 folder whitelist tidak ada
set -u
CONF="${CONF:-pemeliharaan.conf}"
DATA_DIR="${SOURCE_DIR:-data}"
HARI_INI="${HARI_INI:-$(date +%F)}"
APPLY=0
# --- 1. Baca argumen -----------------------------------------------------
while [ $# -gt 0 ]; do
case "$1" in
--apply) APPLY=1; shift ;;
--data-dir|--config)
if [ $# -lt 2 ]; then
printf 'pemeliharaan.sh: %s butuh nilai\n' "$1" >&2
exit 1
fi
if [ "$1" = "--data-dir" ]; then
DATA_DIR="$2"
else
CONF="$2"
fi
shift 2
;;
*)
printf 'pemeliharaan.sh: argumen tidak dikenal: %s\n' "$1" >&2
exit 1
;;
esac
done
# --- 2. Baca dan validasi konfigurasi ------------------------------------
if [ ! -f "$CONF" ]; then
printf 'pemeliharaan.sh: berkas konfigurasi %s tidak ditemukan\n' "$CONF" >&2
exit 1
fi
# shellcheck source=/dev/null
. "$CONF"
if [ -z "${CACHE_DIRS:-}" ] && [ -z "${LOG_DIRS:-}" ] && [ -z "${TMP_DIRS:-}" ]; then
printf 'pemeliharaan.sh: whitelist kosong (CACHE_DIRS/LOG_DIRS/TMP_DIRS) di %s\n' "$CONF" >&2
exit 1
fi
valid_umur() {
case $1 in
''|*[!0-9]*|0) return 1 ;;
esac
return 0
}
valid_umur "${CACHE_MAX_DAYS:-}" || {
printf 'pemeliharaan.sh: CACHE_MAX_DAYS harus angka 1 atau lebih\n' >&2; exit 1; }
valid_umur "${LOG_MAX_DAYS:-}" || {
printf 'pemeliharaan.sh: LOG_MAX_DAYS harus angka 1 atau lebih\n' >&2; exit 1; }
valid_umur "${TMP_MAX_DAYS:-}" || {
printf 'pemeliharaan.sh: TMP_MAX_DAYS harus angka 1 atau lebih\n' >&2; exit 1; }
case ${DISK_WARN_PCT:-} in
''|*[!0-9]*|0)
printf 'pemeliharaan.sh: DISK_WARN_PCT harus angka 1-99\n' >&2
exit 1
;;
esac
if [ "$DISK_WARN_PCT" -gt 99 ]; then
printf 'pemeliharaan.sh: DISK_WARN_PCT harus angka 1-99\n' >&2
exit 1
fi
# Mode sengaja di set SETELAH konfigurasi dibaca: walau berkas
# konfigurasi berisi "MODE=apply", nilainya tetap ditimpa di sini.
# Hanya argumen --apply yang boleh menyalakan pembersihan sungguhan.
MODE="dry-run"
if [ "$APPLY" -eq 1 ]; then
MODE="apply"
fi
# --- 3. Validasi snapshot data --------------------------------------------
for f in df.txt paket.txt services.txt; do
if [ ! -f "$DATA_DIR/$f" ]; then
printf 'pemeliharaan.sh: snapshot %s/%s tidak ditemukan\n' "$DATA_DIR" "$f" >&2
exit 2
fi
done
# --- 4. Pemeriksaan -------------------------------------------------------
# Temuan pemeriksaan terkumpul di sini, lalu menjadi bagian laporan.
# Disk: kolom ke-5 df adalah Use%; "+0" di awk membuang karakter '%'
# sehingga "89%" terbaca sebagai angka 89.
DISK_BARIS=$(awk -v ambang="$DISK_WARN_PCT" '
NR > 1 {
pct = $5 + 0
if (pct >= ambang)
printf " %-10s %3d%% WASPADA\n", $6, pct
else
printf " %-10s %3d%% OK\n", $6, pct
}' "$DATA_DIR/df.txt")
DISK_MELEBIHI=$(awk -v ambang="$DISK_WARN_PCT" '
NR > 1 && ($5 + 0) >= ambang {
printf "%s%s", pisah, $6
pisah = ", "
}' "$DATA_DIR/df.txt")
DISK_N=$(awk -v ambang="$DISK_WARN_PCT" '
NR > 1 && ($5 + 0) >= ambang { n++ } END { print n + 0 }' "$DATA_DIR/df.txt")
# Paket tertunda: output simulasi apt-get -s upgrade menandai tiap paket
# dengan satu baris "Inst <nama> [versi lama] (versi baru)".
PAKET_DAFTAR=$(awk '/^Inst / {
printf "%s%s", pisah, $2
pisah = ", "
}' "$DATA_DIR/paket.txt")
PAKET_N=$(awk '/^Inst / { n++ } END { print n + 0 }' "$DATA_DIR/paket.txt")
# Service gagal: snapshot berformat "unit substate" per baris.
SVC_DAFTAR=$(awk '$2 == "failed" {
printf "%s%s", pisah, $1
pisah = ", "
}' "$DATA_DIR/services.txt")
SVC_N=$(awk '$2 == "failed" { n++ } END { print n + 0 }' "$DATA_DIR/services.txt")
# --- 5. Pembersihan (hanya di dalam whitelist) -----------------------------
# Hasil pembersihan terkumpul di BAG_BERSIH; penghitung JUMLAH_FILE dan
# HEMAT_BYTES dipakai seksi HEMAT RUANG di laporan.
JUMLAH_FILE=0
HEMAT_BYTES=0
BAG_BERSIH=""
# bersihkan <judul> <dirs> <umur-hari> <pola-nama>:
# kumpulkan file di folder whitelist yang lebih tua dari batas umur,
# catat ukurannya untuk laporan, dan hapus hanya bila mode apply.
# -type f menjaga folder tetap utuh; find hanya berangkat dari folder
# whitelist, jadi file di luar daftar tidak pernah tersentuh.
bersihkan() {
judul="$1"
dirs="$2"
umur="$3"
pola="${4:-*}"
batas=$(date -d "$HARI_INI -$umur days" +%F)
if [ "$pola" = "*" ]; then
label="file"
else
label="file $pola"
fi
terpakai=0
if [ -n "$BAG_BERSIH" ]; then
BAG_BERSIH+=$'\n'
fi
BAG_BERSIH+="$judul — $label lebih tua dari $batas (whitelist: $dirs)"$'\n'
# shellcheck disable=SC2086 # whitelist memang dipisah spasi
for dir in $dirs; do
if [ ! -d "$dir" ]; then
printf 'pemeliharaan.sh: folder whitelist %s tidak ditemukan\n' "$dir" >&2
exit 3
fi
# Process substitution < <(...) menjaga penghitung tetap hidup
# di shell utama; pipeline biasa akan menjalankan while di
# subshell sehingga JUMLAH_FILE hilang.
while IFS= read -r f; do
[ -n "$f" ] || continue
ukuran=$(stat -c %s "$f")
JUMLAH_FILE=$((JUMLAH_FILE + 1))
HEMAT_BYTES=$((HEMAT_BYTES + ukuran))
terpakai=$((terpakai + 1))
if [ "$MODE" = "apply" ]; then
rm -f -- "$f"
BAG_BERSIH+=" [terhapus] $f (${ukuran} byte)"$'\n'
else
BAG_BERSIH+=" [dry-run] $f (${ukuran} byte)"$'\n'
fi
done < <(find "$dir" -type f -name "$pola" ! -newermt "$batas" | sort)
done
if [ "$terpakai" -eq 0 ]; then
BAG_BERSIH+=" (tidak ada kandidat)"$'\n'
fi
}
if [ -n "${CACHE_DIRS:-}" ]; then
bersihkan "cache" "$CACHE_DIRS" "$CACHE_MAX_DAYS"
fi
if [ -n "${LOG_DIRS:-}" ]; then
bersihkan "log" "$LOG_DIRS" "$LOG_MAX_DAYS" "*.gz"
fi
if [ -n "${TMP_DIRS:-}" ]; then
bersihkan "tmp" "$TMP_DIRS" "$TMP_MAX_DAYS"
fi
# --- 6. Susun laporan -----------------------------------------------------
if [ "$MODE" = "apply" ]; then
LABEL_MODE="APPLY (pembersihan benar-benar dijalankan)"
LABEL_HEMAT="benar-benar dibebaskan dari disk"
else
LABEL_MODE="DRY-RUN (tidak ada file yang dihapus)"
LABEL_HEMAT="potensi hemat; jalankan --apply untuk benar-benar menghapus"
fi
LAPORAN=""
tambah() {
LAPORAN+="$1"
LAPORAN+=$'\n'
}
tambah "================================================================"
tambah "LAPORAN PEMELIHARAAN SISTEM"
tambah "Tanggal acuan : $HARI_INI"
tambah "Mode : $LABEL_MODE"
tambah "================================================================"
tambah ""
tambah "PEMERIKSAAN"
tambah "----------------------------------------------------------------"
tambah "1. Pemakaian disk (ambang $DISK_WARN_PCT%)"
tambah "$DISK_BARIS"
tambah "2. Paket update tertunda"
if [ "$PAKET_N" -gt 0 ]; then
tambah " $PAKET_N paket siap di-upgrade: $PAKET_DAFTAR"
else
tambah " tidak ada paket tertunda"
fi
tambah "3. Service gagal"
if [ "$SVC_N" -gt 0 ]; then
tambah " $SVC_N service failed: $SVC_DAFTAR"
else
tambah " semua service berjalan normal"
fi
tambah ""
tambah "PEMBERSIHAN"
tambah "----------------------------------------------------------------"
tambah "${BAG_BERSIH%$'\n'}"
tambah ""
tambah "HEMAT RUANG"
tambah "----------------------------------------------------------------"
tambah "Total: $JUMLAH_FILE file, $HEMAT_BYTES byte ($LABEL_HEMAT)"
tambah ""
tambah "REKOMENDASI"
tambah "----------------------------------------------------------------"
nomor=1
if [ "$DISK_N" -gt 0 ]; then
tambah "$nomor. Pemakaian disk melewati ambang $DISK_WARN_PCT% di $DISK_MELEBIHI:"
tambah " cari penyumbang terbesar dengan du -h, lalu bersihkan atau pindahkan."
nomor=$((nomor + 1))
fi
if [ "$PAKET_N" -gt 0 ]; then
tambah "$nomor. Ada $PAKET_N paket update tertunda:"
tambah " jalankan apt upgrade pada jadwal maintenance berikutnya."
nomor=$((nomor + 1))
fi
if [ "$SVC_N" -gt 0 ]; then
tambah "$nomor. Ada $SVC_N service gagal ($SVC_DAFTAR):"
tambah " periksa journalctl -u <unit> untuk penyebabnya, lalu restart bila aman."
nomor=$((nomor + 1))
fi
if [ "$MODE" = "dry-run" ] && [ "$JUMLAH_FILE" -gt 0 ]; then
tambah "$nomor. DRY-RUN menemukan $JUMLAH_FILE file ($HEMAT_BYTES byte) layak dibersihkan:"
tambah " periksa daftar di bagian PEMBERSIHAN, lalu jalankan ulang dengan --apply."
nomor=$((nomor + 1))
fi
if [ "$nomor" -eq 1 ]; then
tambah "1. Tidak ada temuan: sistem dalam kondisi baik. Ulangi pemeliharaan sesuai jadwal."
fi
# --- 7. Tulis laporan ke stdout dan berkas ---------------------------------
REPORT_FILE="${REPORT_FILE:-laporan-pemeliharaan.txt}"
mkdir -p "$(dirname "$REPORT_FILE")"
printf '%s' "$LAPORAN" | tee "$REPORT_FILE"
exit 0
tests/run-tests.sh
Unduh berkas#!/usr/bin/env bash
# run-tests.sh — test suite untuk pemeliharaan.sh.
# Suite menyiapkan sendiri folder kerja terisolasi (mktemp) beserta
# data contohnya — snapshot beku (df.txt, paket.txt, services.txt) dan
# file cache/log/tmp dengan mtime beku lewat touch -d — lalu menjalankan
# rangkaian pengujian dengan assertion sederhana. Jalankan dari mana
# saja: bash tests/run-tests.sh
set -u
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
PROJ_DIR=$(dirname "$SCRIPT_DIR")
PASS=0
FAIL=0
# assert_eq <harapan> <nyata> <pesan>: bandingkan dua nilai.
assert_eq() {
if [ "$1" = "$2" ]; then
PASS=$((PASS + 1))
printf 'OK %s\n' "$3"
else
FAIL=$((FAIL + 1))
printf 'GAGAL %s: harapan %s, nyata %s\n' "$3" "$1" "$2"
fi
}
# --- siapkan folder kerja terisolasi ------------------------------------
WORK=$(mktemp -d)
cp "$PROJ_DIR/src/pemeliharaan.sh" "$PROJ_DIR/config/pemeliharaan.conf" "$WORK/"
cd "$WORK" || exit 1
# --- fixture: snapshot data beku ----------------------------------------
mkdir -p data/cache data/log data/tmp
cat > data/df.txt <<'EOF'
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 50G 35G 13G 73% /
/dev/sdb1 200G 170G 21G 89% /data
tmpfs 7.8G 1.1M 7.8G 1% /dev/shm
EOF
cat > data/paket.txt <<'EOF'
Reading package lists... Done
Building dependency tree... Done
Calculating upgrade... Done
Reading state information... Done
The following packages will be upgraded:
curl libcurl4 libssl3 openssl
4 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Inst curl [7.88.1-10] (7.88.1-11)
Inst libcurl4 [7.88.1-10] (7.88.1-11)
Inst libssl3 [3.0.8-1] (3.0.8-2)
Inst openssl [3.0.8-1] (3.0.8-2)
Conf curl (7.88.1-11)
Conf libcurl4 (7.88.1-11)
Conf libssl3 (3.0.8-2)
Conf openssl (3.0.8-2)
EOF
cat > data/services.txt <<'EOF'
nginx.service failed
postgresql.service failed
sshd.service running
cron.service running
EOF
# --- fixture: file dengan mtime beku -------------------------------------
# Tanggal acuan pengujian: 2026-02-15. Batas umur menjadi
# cache 30 hari -> 2026-01-16, log 14 hari -> 2026-02-01,
# tmp 7 hari -> 2026-02-08.
printf 'isi cache lama\n' > data/cache/lama.txt
touch -d "2026-01-10" data/cache/lama.txt
printf 'isi cache baru\n' > data/cache/baru.txt
touch -d "2026-02-10" data/cache/baru.txt
printf 'isi log lama terkompresi\n' > data/log/app.log.1.gz
touch -d "2026-01-25" data/log/app.log.1.gz
printf 'isi log lama tapi bukan gz\n' > data/log/app.log
touch -d "2026-01-20" data/log/app.log
printf 'isi log baru\n' > data/log/app.log.2.gz
touch -d "2026-02-12" data/log/app.log.2.gz
printf 'sisa instalasi lama\n' > data/tmp/sisa.tmp
touch -d "2026-02-01" data/tmp/sisa.tmp
printf 'file tmp aktif\n' > data/tmp/aktif.tmp
touch -d "2026-02-13" data/tmp/aktif.tmp
# Ukuran total yang harus dibebaskan mode apply: tiga file tua.
total_hemat=$(stat -c %s data/cache/lama.txt data/log/app.log.1.gz \
data/tmp/sisa.tmp | awk '{ s += $1 } END { print s }')
# --- uji 1: dry-run sukses dan tidak menghapus ---------------------------
HARI_INI=2026-02-15 bash pemeliharaan.sh > /dev/null 2>&1
assert_eq 0 "$?" "dry-run sukses keluar 0"
[ -f data/cache/lama.txt ]
assert_eq 0 "$?" "dry-run tidak menghapus cache lama"
[ -f data/log/app.log.1.gz ]
assert_eq 0 "$?" "dry-run tidak menghapus log lama"
# --- uji 2: laporan dibuat dengan empat seksi ----------------------------
[ -f laporan-pemeliharaan.txt ]
assert_eq 0 "$?" "berkas laporan dibuat"
grep -q '^PEMERIKSAAN$' laporan-pemeliharaan.txt
assert_eq 0 "$?" "laporan memuat seksi PEMERIKSAAN"
grep -q '^PEMBERSIHAN$' laporan-pemeliharaan.txt
assert_eq 0 "$?" "laporan memuat seksi PEMBERSIHAN"
grep -q '^HEMAT RUANG$' laporan-pemeliharaan.txt
assert_eq 0 "$?" "laporan memuat seksi HEMAT RUANG"
grep -q '^REKOMENDASI$' laporan-pemeliharaan.txt
assert_eq 0 "$?" "laporan memuat seksi REKOMENDASI"
# --- uji 3: parsing ketiga pemeriksaan benar ------------------------------
grep -q '89% WASPADA' laporan-pemeliharaan.txt
assert_eq 0 "$?" "disk 89% ditandai WASPADA"
grep -q '73% OK' laporan-pemeliharaan.txt
assert_eq 0 "$?" "disk 73% ditandai OK"
grep -q '4 paket siap di-upgrade: curl, libcurl4, libssl3, openssl' \
laporan-pemeliharaan.txt
assert_eq 0 "$?" "jumlah dan daftar paket tertunda benar"
grep -q '2 service failed: nginx.service, postgresql.service' \
laporan-pemeliharaan.txt
assert_eq 0 "$?" "jumlah dan daftar service gagal benar"
# --- uji 4: daftar kandidat dan rekomendasi dry-run ------------------------
grep -Fq '[dry-run] data/cache/lama.txt' laporan-pemeliharaan.txt
assert_eq 0 "$?" "dry-run menampilkan kandidat cache"
grep -Fq '[dry-run] data/log/app.log.1.gz' laporan-pemeliharaan.txt
assert_eq 0 "$?" "dry-run menampilkan kandidat log"
grep -Fq '[dry-run] data/tmp/sisa.tmp' laporan-pemeliharaan.txt
assert_eq 0 "$?" "dry-run menampilkan kandidat tmp"
grep -q 'jalankan ulang dengan --apply' laporan-pemeliharaan.txt
assert_eq 0 "$?" "rekomendasi menyarankan --apply"
# --- uji 5: dua run dry-run menghasilkan laporan identik -------------------
cp laporan-pemeliharaan.txt laporan-run1.txt
HARI_INI=2026-02-15 bash pemeliharaan.sh > /dev/null 2>&1
assert_eq 0 "$?" "dry-run kedua sukses keluar 0"
diff laporan-run1.txt laporan-pemeliharaan.txt > /dev/null 2>&1
assert_eq 0 "$?" "dua laporan dry-run identik"
# --- uji 6: apply menghapus yang benar saja -------------------------------
HARI_INI=2026-02-15 bash pemeliharaan.sh --apply > /dev/null 2>&1
assert_eq 0 "$?" "apply sukses keluar 0"
[ ! -f data/cache/lama.txt ]
assert_eq 0 "$?" "apply menghapus cache lama"
[ ! -f data/log/app.log.1.gz ]
assert_eq 0 "$?" "apply menghapus log gz lama"
[ ! -f data/tmp/sisa.tmp ]
assert_eq 0 "$?" "apply menghapus tmp lama"
[ -f data/cache/baru.txt ]
assert_eq 0 "$?" "cache baru tetap ada"
[ -f data/log/app.log ]
assert_eq 0 "$?" "log lama non-gz tetap ada (pola hanya *.gz)"
[ -f data/log/app.log.2.gz ]
assert_eq 0 "$?" "log gz baru tetap ada"
[ -f data/tmp/aktif.tmp ]
assert_eq 0 "$?" "tmp baru tetap ada"
# --- uji 7: laporan apply akurat -------------------------------------------
terhapus=$(grep -Fc '[terhapus]' laporan-pemeliharaan.txt)
assert_eq 3 "$terhapus" "laporan apply mencatat 3 file terhapus"
grep -q "Total: 3 file, $total_hemat byte (benar-benar dibebaskan dari disk)" \
laporan-pemeliharaan.txt
assert_eq 0 "$?" "total hemat ruang cocok dengan jumlah byte fixture"
! grep -q 'jalankan ulang dengan --apply' laporan-pemeliharaan.txt
assert_eq 0 "$?" "laporan apply tidak menyarankan --apply lagi"
# --- uji 8: exit code untuk tiap jenis kegagalan ----------------------------
CONF=nihil.conf HARI_INI=2026-02-15 bash pemeliharaan.sh > /dev/null 2>&1
assert_eq 1 "$?" "konfigurasi hilang keluar 1"
printf 'CACHE_DIRS="data/cache"\nLOG_DIRS=""\nTMP_DIRS=""\nCACHE_MAX_DAYS=abc\nLOG_MAX_DAYS=14\nTMP_MAX_DAYS=7\nDISK_WARN_PCT=80\n' > umur-rusak.conf
CONF=umur-rusak.conf HARI_INI=2026-02-15 bash pemeliharaan.sh > /dev/null 2>&1
assert_eq 1 "$?" "umur tidak angka keluar 1"
mkdir -p data-kosong
SOURCE_DIR=data-kosong HARI_INI=2026-02-15 bash pemeliharaan.sh > /dev/null 2>&1
assert_eq 2 "$?" "snapshot hilang keluar 2"
printf 'CACHE_DIRS="data/cache"\nLOG_DIRS="data/log"\nTMP_DIRS="data/tidak-ada"\nCACHE_MAX_DAYS=30\nLOG_MAX_DAYS=14\nTMP_MAX_DAYS=7\nDISK_WARN_PCT=80\n' > whitelist-rusak.conf
CONF=whitelist-rusak.conf HARI_INI=2026-02-15 bash pemeliharaan.sh > /dev/null 2>&1
assert_eq 3 "$?" "folder whitelist hilang keluar 3"
HARI_INI=2026-02-15 bash pemeliharaan.sh --bogus > /dev/null 2>&1
assert_eq 1 "$?" "argumen tak dikenal keluar 1"
# --- ringkasan --------------------------------------------------------------
if [ "$FAIL" -eq 0 ]; then
printf 'PASSED: %d/%d test lulus\n' "$PASS" "$PASS"
else
printf 'FAILED: %d/%d test lulus\n' "$PASS" "$((PASS + FAIL))"
fi
cd / && rm -rf "$WORK"
[ "$FAIL" -eq 0 ]