Bali, Indonesia
Insights

Cara Cek Script init.d Lama Tetap Jalan Benar di systemd Setelah Upgrade OS

October 25, 2026
0:00
Setelah upgrade OS, banyak service lama yang masih dijalankan lewat script di /etc/init.d/ terlihat baik-baik saja. systemctl status bilang active, tidak ada pesan error, tapi aplikasinya tidak merespons. Kasus lain, service jalan normal saat di-start manual, lalu tidak muncul lagi setelah server reboot. Penyebabnya biasanya sama: script itu tidak dijalankan systemd secara langsung. systemd membungkusnya dengan unit buatan otomatis, dan unit ini punya perilaku yang berbeda dari unit native. Artikel ini fokus ke cara mengeceknya lewat CLI. Tujuannya supaya kamu bisa membedakan service yang benar-benar hidup dari service yang cuma terlihat hidup di status.
systemd punya mekanisme bernama generator. Generator adalah program kecil yang dijalankan saat boot dan setiap kali kamu menjalankan systemctl daemon-reload. Salah satunya, systemd-sysv-generator, bertugas memindai script di /etc/init.d/. Generator membaca header LSB di bagian atas script (blok ### BEGIN INIT INFO sampai ### END INIT INFO), lalu membuat file .service sementara untuk tiap script. File hasil generator itu tidak ditulis ke /etc/systemd/system/ atau /lib/systemd/system/, melainkan ke direktori runtime di bawah /run/systemd/. Ini sering bikin bingung. Admin mencari file unit-nya di lokasi biasa, tidak ketemu, lalu mengira service itu tidak dikelola systemd sama sekali. Satu hal lagi yang perlu diingat: kalau sudah ada unit native dengan nama yang sama, generator akan melewati script init.d-nya. Jadi bisa saja script yang kamu edit ternyata tidak pernah dipakai. Bagian yang paling penting adalah properti unit hasil generator. Umumnya unit ini memakai Type=forking, RemainAfterExit=yes, Restart=no, dan GuessMainPID=no. Artinya kurang lebih begini:
  • systemd menganggap tugas script selesai begitu start berhasil keluar.
  • Unit tetap dianggap aktif meski proses yang dijalankan script sudah tidak ada.
  • Kalau prosesnya crash, systemd tidak akan me-restart-nya.
  • systemd tidak berusaha menebak proses mana yang jadi proses utama.
Di meja support, pola ini sering muncul sebagai keluhan "service-nya aktif tapi website-nya mati". Yang pertama perlu dicek adalah apakah unit itu native atau hasil generator.
Sebelum menyimpulkan apa pun, pastikan dari mana unit itu berasal. Ganti nama-app dengan nama script di /etc/init.d/ milikmu. Semua perintah di bawah ini read-only.
BASH
# Lihat unit apa saja yang dibuat generator di boot ini
ls -l /run/systemd/generator.late/

# Tampilkan isi unit. Unit hasil generator biasanya diawali komentar
# yang menyebut systemd-sysv-generator dan punya SourcePath ke /etc/init.d
systemctl cat nama-app.service

# Ambil properti kunci dalam satu perintah
systemctl show -p SourcePath -p FragmentPath -p Type -p RemainAfterExit -p Restart nama-app.service
Kalau SourcePath mengarah ke /etc/init.d/nama-app dan FragmentPath berada di bawah /run/systemd/, berarti service itu memang dibungkus generator. Kalau FragmentPath justru menunjuk ke /etc/systemd/system/ atau /lib/systemd/system/, berarti ada unit native yang menang. Dalam kasus itu, perubahan apa pun di script init.d tidak akan berpengaruh. Kondisi ini sering terjadi setelah upgrade, karena paket versi baru kadang membawa unit native sendiri. Perhatikan juga nilai RemainAfterExit dan Restart. Dua nilai ini menjelaskan hampir semua kebingungan di bagian berikutnya.
Dengan RemainAfterExit=yes, systemd mencatat unit sebagai aktif begitu perintah start di script selesai dengan kode keluar sukses. Setelah itu, kalau daemon yang dijalankan script mati karena crash, kehabisan memori, atau error konfigurasi yang baru terbaca belakangan, unit tetap tercatat aktif. Di output status, kondisi ini biasanya muncul sebagai active (exited), bukan active (running). Banyak orang hanya membaca kata active dan berhenti di situ. Padahal kata di dalam kurung itulah yang penting. exited pada service yang seharusnya berupa daemon jangka panjang adalah tanda kamu perlu mengecek prosesnya langsung.
BASH
# Status lengkap. Perhatikan baris Active dan daftar proses di bagian CGroup
systemctl status nama-app.service --no-pager

# MainPID 0 berarti systemd tidak melacak proses utama
systemctl show -p ActiveState -p SubState -p MainPID nama-app.service

# Proses apa saja yang masih ada di cgroup unit ini
systemd-cgls -u nama-app.service

# Cek proses dan port langsung, tanpa lewat systemd
pgrep -af nama-app
sudo ss -ltnp
Baca hasilnya dengan urutan seperti ini:
  1. Kalau SubState bernilai exited dan cgroup kosong, unit cuma "ingat" bahwa dulu start-nya berhasil. Prosesnya sudah tidak ada.
  2. Kalau pgrep menemukan prosesnya tapi cgroup unit kosong, kemungkinan daemon dijalankan di luar systemd. Misalnya ada yang menjalankan /etc/init.d/nama-app start langsung, bukan lewat systemctl. Proses seperti ini tidak dilacak unit, jadi systemctl stop pun tidak akan menghentikannya dengan benar.
  3. Terakhir, cocokkan port di ss dengan port yang seharusnya dipakai aplikasi. Kalau port-nya tidak ada di daftar listen, service itu tidak melayani apa pun, apa pun kata status.
Karena Restart=no, systemd juga tidak akan mencoba menghidupkan ulang daemon yang mati. Di sistem lama berbasis SysV, perilakunya memang sama. Bedanya, sekarang status di systemd memberi kesan semuanya aman.
Masalah kedua yang sering muncul: service jalan setelah di-start manual, tapi tidak ikut start setelah reboot. Untuk script SysV, status enable tidak disimpan sebagai symlink di /etc/systemd/system/*.wants/ seperti unit native. Generator menentukannya dari symlink S* di direktori /etc/rc?.d/, yang dibuat dari nilai Default-Start di header LSB. Perintah systemctl is-enabled untuk script SysV biasanya diteruskan ke tool bawaan distro. Di keluarga Debian/Ubuntu ke systemd-sysv-install, di keluarga RHEL ke chkconfig. Karena itu output-nya kadang disertai pesan bahwa service tersebut bukan service native. Pesan ini wajar, bukan error.
BASH
# Status enable menurut systemd (dan tool SysV di belakangnya)
systemctl is-enabled nama-app.service

# Symlink runlevel yang dipakai generator. S = start, K = kill
ls -l /etc/rc?.d/ | grep nama-app

# Apakah unit masuk ke dependensi target boot normal
systemctl list-dependencies multi-user.target --no-pager | grep nama-app

# Log unit untuk boot saat ini, lalu boot sebelumnya
journalctl -u nama-app.service -b --no-pager
journalctl -u nama-app.service -b -1 --no-pager

# Rantai dependensi yang menunda atau mendahului service ini saat boot
systemd-analyze critical-chain nama-app.service
Kalau is-enabled menjawab enabled tapi unit tidak muncul di list-dependencies target boot, periksa header LSB di script. Header yang hilang, Default-Start yang kosong, atau Required-Start yang menyebut facility yang tidak dikenal bisa membuat urutan atau penempatan unit tidak sesuai harapan. Setelah memperbaiki header, jalankan sudo systemctl daemon-reload supaya generator membaca ulang script. Perintah ini aman dan tidak me-restart service. Untuk journalctl -b -1, log boot sebelumnya hanya tersedia kalau journal disimpan permanen. Kalau perintah itu menjawab tidak ada data boot sebelumnya, cek dulu konfigurasi journald. Pembahasannya ada di cara cek journald menyimpan log permanen setelah pindah dari rsyslog. Tanpa log boot sebelumnya, kamu cuma bisa menebak kenapa service gagal start saat boot. Yang biasanya terlihat di journal untuk unit hasil generator adalah output dari script itu sendiri, misalnya pesan Starting ... dan kode keluar. Kalau script menyembunyikan error daemon ke /dev/null atau ke file log sendiri, journal akan terlihat bersih padahal daemon gagal. Dalam kasus ini, buka juga file log aplikasi yang disebut di script.
Pengecekan di atas baru meyakinkan setelah diuji lewat reboot sungguhan di jam yang aman. Sesudah server kembali, ulangi tiga hal dengan urutan yang sama:
  1. systemctl show -p SubState -p MainPID untuk melihat status unit.
  2. systemd-cgls -u dan ss -ltnp untuk memastikan prosesnya hidup dan port-nya listen.
  3. journalctl -u ... -b untuk membaca apa yang terjadi saat boot.
Kalau ketiganya konsisten, service itu memang jalan dan ikut boot. Kalau status bilang aktif tapi poin kedua kosong, berarti kamu sedang melihat efek RemainAfterExit. Bungkus dari generator ini pada dasarnya adalah lapisan kompatibilitas, bukan tujuan akhir. Upstream systemd sudah lama menandai dukungan script SysV sebagai deprecated. Di versi baru, dukungan ini direncanakan atau sudah dihapus, jadi cek changelog systemd dan catatan rilis distro kamu sebelum upgrade berikutnya. Unit native juga menyelesaikan masalah yang dibahas di sini. Dengan Type=simple atau Type=notify, systemd melacak proses utama secara langsung. Dengan Restart=on-failure, daemon yang crash dihidupkan ulang. Status active (running) pun benar-benar berarti prosesnya ada. Saat pertama kali menulis unit native, error paling umum adalah service langsung gagal karena path atau izin eksekusi di ExecStart. Kalau itu terjadi, panduan melacak service systemd yang keluar dengan status 203/EXEC bisa membantu. Ingat juga bahwa unit native dengan nama yang sama akan langsung menggantikan script init.d setelah daemon-reload. Hentikan dulu service lama lewat systemctl stop supaya tidak ada dua instance yang berebut port. Aturan praktisnya sederhana. Untuk service yang berasal dari /etc/init.d/, jangan pernah percaya kata active saja. Pastikan dulu unit-nya hasil generator lewat systemctl show -p SourcePath. Lalu cocokkan SubState, isi cgroup, dan port yang listen. Kalau service itu penting untuk produksi, jadwalkan pemindahannya ke unit native, sebelum upgrade OS berikutnya membuat lapisan kompatibilitas ini hilang.