Menjalankan program di server itu gampang: ketik perintahnya, tekan Enter, selesai. Masalahnya muncul beberapa jam kemudian. Terminal ditutup, program ikut mati. Server reboot, program tidak pernah bangun lagi. Dan tidak ada yang tahu kalau program itu sudah berhenti sejak jam tiga pagi.
Di sinilah service berperan. Service bukan program yang lebih hebat, tapi kontrak tertulis yang memberitahu systemd: program apa yang dijalankan, sebagai user siapa, dari folder mana, dan apa yang harus dilakukan kalau program itu mati. Artikel ini membahas cara membuat kontrak itu sendiri, bukan sekadar memakai service bawaan paket.
π― Tujuan
Setelah membaca dan mempraktikkan artikel ini, kamu diharapkan bisa:
- Menjelaskan beda "program yang dijalankan" dan "program yang dijadikan service".
- Menulis file unit
.servicesendiri dengan tiga bagian yang benar. - Memilih
Type=yang cocok:simple,oneshot, atauforking. - Memakai
User=danWorkingDirectory=supaya service tidak jalan sebagai root dan tidak salah folder. - Membedakan
start,enable, danenable --now. - Membaca kegagalan service dari
systemctl statusdanjournalctltanpa menebak-nebak.
π Konteks nyata
Bayangkan kamu punya tukang panggilan. Selama kamu telepon, dia datang dan bekerja. Tapi begitu kamu berhenti mengawasi, dia pulang tanpa kabar. Kalau kamu sakit dan tidak bisa menelepon, tidak ada yang datang.
Program yang kamu jalankan manual persis seperti itu. Service adalah kontrak kerja dengan manajer gedung: jam masuk, nama petugas, ruang kerja, dan aturan "kalau tidak masuk tanpa kabar, hubungi saya". Manajer gedungnya adalah systemd.
π‘ Tips: Kalau kamu masih menjalankan skrip penting dengan nohup atau & di terminal SSH, itu tanda paling jelas bahwa skrip tersebut butuh service. nohup hanya menunda masalah, tidak menyelesaikannya.
π₯ Kasus nyata: Sebuah SMK punya skrip penyalin nilai dari aplikasi ujian ke server rapor. Skrip itu dijalankan manual oleh guru piket dengan nohup setiap sore. Suatu hari listrik padam malam hari, server hidup lagi pagi, tapi skrip tidak. Selama dua hari nilai tiga kelas tidak tersalin, dan panitia mengira server rapornya rusak. Setelah dijadikan service dengan Restart=on-failure, masalah yang sama tidak terulang saat listrik padam berikutnya.
π§ Konsep singkat
File unit adalah file teks biasa berformat INI. Tidak ada bahasa pemrograman di dalamnya, hanya baris Kunci=nilai yang dikelompokkan dalam tiga bagian.
πΉ Tiga bagian yang wajib kamu kenal
Tabel berikut adalah kerangka minimal yang berlaku untuk hampir semua service.
| Bagian | Isi | Menjawab pertanyaan |
|---|---|---|
[Unit] |
Description, After, Wants |
Ini service apa, dan kapan boleh dijalankan? |
[Service] |
Type, ExecStart, User, Restart |
Dijalankan bagaimana, oleh siapa, dari mana? |
[Install] |
WantedBy=multi-user.target |
Hidup otomatis saat boot atau tidak? |
Bagian [Install] punya sifat khusus yang sering disalahpahami: isinya tidak dibaca saat service berjalan. Bagian itu hanya dipakai ketika kamu menjalankan systemctl enable, untuk membuat symlink di multi-user.target.wants/.
πΉ Type: kapan systemd menganggap service "sudah jalan"
Ini keputusan paling penting, dan yang paling sering salah pilih.
| Type | Dianggap jalan saat | Cocok untuk |
|---|---|---|
simple |
proses sudah di-fork (default) | program yang jalan terus, mis. daemon buatan sendiri |
exec |
binary berhasil dieksekusi | sama seperti simple, tapi gagal exec ikut dilaporkan |
oneshot |
proses selesai | skrip sekali jalan, migrasi, backup |
forking |
proses induk keluar | daemon lama yang mem-fork ke background |
notify |
program mengirim sd_notify | aplikasi modern yang siap melapor |
β οΈ Hati-hati: Pada Type=simple, systemctl start bisa melapor sukses walaupun binary-nya tidak ada atau User=-nya tidak dikenal. Sebab systemd menganggap service jalan tepat setelah proses di-fork, sebelum eksekusi binary benar-benar terjadi. Kalau kamu ingin kegagalan itu langsung terlihat, pakai Type=exec.
π Angka penting: Default RestartSec= hanya 100 milidetik. Kalau programmu butuh waktu untuk melepas port atau menunggu database siap, restart serapat itu justru membuatnya gagal berulang. Isi sendiri, misalnya 5s.
πΉ Restart: siapa yang menghidupkan ulang
Restart= menentukan apakah systemd mencoba menyalakan ulang service yang berhenti. Nilai yang umum dipakai:
noβ tidak pernah dihidupkan ulang. Cocok untukoneshot.on-failureβ hanya kalau keluar dengan kode error atau dibunuh sinyal. Ini pilihan paling aman untuk pemula.on-successβ hanya kalau keluar bersih. Jarang dipakai.alwaysβ selalu, termasuk setelah keluar normal. Cocok untuk program yang memang harus hidup terus.
Percobaan restart tidak tak terbatas. systemd punya pengaman bernama start limit yang diatur StartLimitIntervalSec= dan StartLimitBurst= di bagian [Unit]. Kalau batas terlampaui, service masuk status failed dengan pesan "start request repeated too quickly".
π₯ Kasus nyata: Sebuah kantor distributor memasang skrip sinkronisasi stok sebagai service dengan Restart=always dan RestartSec=1. Karena database belum siap saat boot, skrip gagal, restart, gagal lagi. Dalam satu menit service terkunci status failed dan tidak pernah mencoba lagi sampai admin sadar. Perbaikannya dua baris: RestartSec=10s dan After=network-online.target mariadb.service.
πΉ Di mana file unit disimpan
systemd mencari file unit di beberapa folder dengan urutan prioritas. Untuk service buatanmu sendiri, tempat yang benar adalah /etc/systemd/system/.
| Lokasi | Isi | Siapa yang menulis |
|---|---|---|
/etc/systemd/system/ |
unit buatan admin | kamu |
/usr/lib/systemd/system/ |
unit dari paket | pembuat paket |
/run/systemd/system/ |
unit sementara | sistem saat runtime |
Jangan pernah mengedit file di /usr/lib/systemd/system/. File itu milik paket dan akan tertimpa saat apt upgrade. Untuk mengubah perilaku service bawaan, pakai drop-in lewat systemctl edit nama.service.
πΉ Tiga perintah yang sering tertukar
systemctl startβ jalankan sekarang, tidak otomatis saat boot.systemctl enableβ daftarkan agar jalan saat boot, tapi belum dijalankan sekarang.systemctl enable --nowβ keduanya sekaligus. Ini yang paling sering kamu butuhkan.
Setiap kali file unit diubah, systemd perlu membaca ulang: systemctl daemon-reload. Tanpa itu, perubahan tidak berlaku dan kamu akan bingung kenapa perbaikannya "tidak ngaruh". Khusus systemctl edit, reload dilakukan otomatis.
π§© Istilah penting
| Istilah | Arti singkat |
|---|---|
| Unit | Satu objek yang dikelola systemd, ditandai akhiran seperti .service
|
| Unit file | File teks berisi definisi unit, biasanya di /etc/systemd/system
|
| Drop-in | File tambahan di nama.service.d/*.conf untuk menimpa sebagian isi unit
|
ExecStart |
Perintah utama yang dijalankan saat service start |
WantedBy |
Target yang "menginginkan" unit ini, dasar pembuatan symlink saat enable |
| Journal | Kumpulan log yang dikelola systemd-journald, dibaca dengan journalctl
|
| Masked | Unit yang dinonaktifkan total lewat symlink ke /dev/null
|
| Start limit | Batas jumlah percobaan start sebelum systemd menyerah |
Satu istilah lagi yang perlu kamu hafal: multi-user.target. Itu nama sistem "siap dipakai banyak user tanpa GUI", pengganti istilah runlevel 3 di zaman SysV.
π§ Praktik: membuat service pertama
Kita akan membuat service pemantau sederhana: mencatat suhu dan pemakaian disk ke file log setiap 60 detik. Tujuannya bukan alat monitoring serius, tapi supaya kamu melihat sendiri semua lapisan bekerja.
πΉ Langkah 1: siapkan skrip dan user khusus
Buat user sistem tanpa shell login, supaya service tidak jalan sebagai root.
sudo useradd --system --no-create-home --shell /usr/sbin/nologin lapor
sudo mkdir -p /var/lib/lapor
sudo chown lapor:lapor /var/lib/lapor
Lalu buat skripnya di /usr/local/bin/lapor-suhu.sh:
#!/usr/bin/env bash
LOG=/var/log/lapor-suhu.log
while true; do
SUHU=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null || echo n/a)
DISK=$(df -h / | awk 'NR==2 {print $5}')
echo "$(date '+%F %T') suhu=$SUHU disk=$DISK" >> "$LOG"
sleep 60
done
sudo install -m 755 -o root -g root /dev/null /usr/local/bin/lapor-suhu.sh
sudo nano /usr/local/bin/lapor-suhu.sh # tempel isi di atas
sudo touch /var/log/lapor-suhu.log
sudo chown lapor:lapor /var/log/lapor-suhu.log
π‘ Tips: Skrip boleh milik root dan mode 755. Yang dijalankan sebagai user lapor adalah prosesnya, bukan pemilik file. Ini praktik yang aman: user biasa tidak bisa mengubah skrip yang dijalankan service.
πΉ Langkah 2: tulis file unit
Simpan sebagai /etc/systemd/system/lapor-suhu.service:
[Unit]
Description=Lapor suhu dan pemakaian disk tiap menit
Documentation=man:systemd.service(5)
After=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Service]
Type=simple
User=lapor
Group=lapor
WorkingDirectory=/var/lib/lapor
ExecStart=/usr/local/bin/lapor-suhu.sh
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Perhatikan tiga hal yang sering dilupakan:
ExecStart=harus path absolut.ExecStart=./lapor-suhu.shditolak dengan pesan "Executable path is not absolute".WorkingDirectory=menentukan folder kerja. Tanpa ini, path relatif di dalam skrip mengarah ke/.User=membuat proses tidak berjalan sebagai root. Kalau user tidak ada, service gagal dengan status217/USER.
πΉ Langkah 3: periksa sebelum menyalakan
systemd-analyze verify /etc/systemd/system/lapor-suhu.service
sudo systemctl daemon-reload
sudo systemctl start lapor-suhu.service
systemctl status lapor-suhu.service --no-pager
Status yang sehat kira-kira berbunyi Active: active (running) dengan Main PID terisi. Kalau tertulis failed, jangan langsung mengubah-ubah file; baca dulu baris Process: ... status=... di bawahnya.
πΉ Langkah 4: buktikan lewat log dan file
journalctl -u lapor-suhu.service -n 20 --no-pager
tail -n 5 /var/log/lapor-suhu.log
Kalau log jurnal kosong tapi file log terisi, itu wajar: skrip menulis sendiri ke file, bukan ke stdout. Justru ini bukti service berjalan.
πΉ Langkah 5: jadikan otomatis saat boot
sudo systemctl enable --now lapor-suhu.service
systemctl is-enabled lapor-suhu.service
systemctl is-active lapor-suhu.service
Keluaran enabled dan active adalah dua hal berbeda. enabled menjawab "apakah dia ikut boot", active menjawab "apakah dia hidup sekarang".
πΉ Langkah 6: ubah tanpa menyentuh file asli
Misalnya kamu ingin restart policy lebih longgar. Jangan edit file utama, pakai drop-in:
sudo systemctl edit lapor-suhu.service
Isi yang muncul adalah file kosong di /etc/systemd/system/lapor-suhu.service.d/override.conf. Tulis hanya bagian yang berubah:
[Service]
RestartSec=30s
Lalu systemctl cat lapor-suhu.service untuk melihat hasil gabungan file asli dan drop-in. Inilah cara yang benar untuk menyesuaikan service milik paket, misalnya Nginx atau SSH.
πΉ Langkah 7: uji kegagalan dengan sengaja
Service yang tidak pernah diuji gagal biasanya gagal di waktu yang paling tidak tepat.
sudo systemctl stop lapor-suhu.service
sudo mv /usr/local/bin/lapor-suhu.sh /root/
sudo systemctl start lapor-suhu.service
systemctl status lapor-suhu.service --no-pager
sudo mv /root/lapor-suhu.sh /usr/local/bin/
sudo systemctl reset-failed lapor-suhu.service
π§ͺ Uji cepat: Setelah skrip dikembalikan, jalankan systemctl reset-failed lalu systemctl start. Kalau kamu lupa reset-failed, service bisa menolak start karena masih terhitung dalam start limit.
π Dipakai di dunia kerja
- Sekolah dan lab komputer: skrip sinkronisasi nilai, penarik absensi, atau pembersih folder ujian dijalankan sebagai service
oneshotagar tidak bergantung pada guru yang ingat menekan Enter. - Kantor dan distributor: aplikasi internal buatan sendiri (antrian cetak, ekspor data harian) dijalankan sebagai service dengan
User=khusus, sehingga mati saat listrik padam bukan berarti mati permanen. - Rumah sakit dan klinik: agen pengirim data ke sistem BPJS atau server pusat harus hidup terus;
Restart=on-failureplus log jurnal adalah syarat minimal sebelum tim IT mau menyerahkannya ke user. - ISP dan penyedia layanan: skrip kecil pemantau link, pengirim metrik, atau pembaru sertifikat dijalankan terjadwal sebagai service atau timer, bukan dari terminal admin yang kebetulan masih terbuka.
- Industri dan pabrik: agen penghubung antara mesin PLC dan dashboard produksi berjalan sebagai service; berhentinya agen berarti dashboard kosong padahal mesin tetap jalan.
- Cloud dan VPS: hampir semua panduan deployment modern berakhir dengan "buat service systemd", karena itu cara paling standar menjaga proses tetap hidup setelah sesi SSH ditutup.
β Verifikasi
Jangan puas dengan "sepertinya jalan". Periksa satu per satu.
| Perintah | Yang dilihat | Harapan |
|---|---|---|
systemctl status lapor-suhu |
Active, Main PID |
active (running)
|
systemctl is-enabled lapor-suhu |
status boot | enabled
|
journalctl -u lapor-suhu -b |
log sejak boot | ada catatan start tanpa error |
systemctl show -p User -p Restart lapor-suhu |
nilai efektif | sesuai file unit |
systemd-analyze verify lapor-suhu.service |
validitas unit | tidak ada peringatan |
ps -o user,pid,cmd -C lapor-suhu.sh |
user proses | lapor, bukan root
|
Uji terakhir yang paling jujur: reboot server, lalu cek systemctl status sebelum menyentuh apa pun. Kalau service hanya hidup setelah kamu start manual, berarti enable-nya belum benar.
β οΈ Kesalahan umum & troubleshooting
| Gejala | Penyebab umum | Perbaikan |
|---|---|---|
status=203/EXEC |
skrip tidak executable atau shebang salah | chmod 755, cek baris #!/usr/bin/env bash
|
status=217/USER |
User= menunjuk user yang tidak ada |
buat user atau perbaiki nama |
status=200/CHDIR |
WorkingDirectory= tidak ada |
buat foldernya atau hapus direktif |
| "Executable path is not absolute" | ExecStart= pakai path relatif |
tulis /usr/local/bin/...
|
| Jalan manual bisa, service gagal | beda user, PATH, atau folder kerja | samakan User= dan WorkingDirectory=
|
| Perubahan tidak berefek | lupa daemon-reload |
systemctl daemon-reload
|
| "start request repeated too quickly" | restart beruntun melewati start limit | perbaiki penyebab, lalu reset-failed
|
| Service mati saat SSH ditutup | masih dijalankan manual di shell | jadikan unit, jangan nohup
|
| Log kosong di jurnal | program menulis ke file sendiri | periksa file log aplikasi |
β οΈ Hati-hati: Kalau service oneshot selesai, statusnya kembali dead dan itu normal. Jangan panik dan menambahkan Restart=always pada skrip migrasi; itu akan menjalankan migrasi berulang-ulang. Untuk oneshot yang ingin tetap tampak aktif, gunakan RemainAfterExit=yes.
β οΈ Hati-hati: Pesan "jalan manual bisa, tapi service gagal" hampir selalu bukan bug systemd. Penyebabnya perbedaan lingkungan: user berbeda, PATH berbeda, folder kerja berbeda, atau variabel dari .bashrc tidak ikut terbaca. Service tidak membaca .bashrc milik siapa pun.
π Catatan keamanan & etika
File unit di /etc/systemd/system/ dieksekusi dengan hak root. Siapa pun yang bisa menulis ke folder itu setara bisa menjalankan perintah sebagai root, jadi jaga permission folder dan jangan longgarkan tanpa alasan.
- Selalu isi
User=danGroup=. Service buatan sendiri hampir tidak pernah perlu root. - Jangan menaruh password di file unit. File unit terbaca semua user. Kalau perlu rahasia, pakai
EnvironmentFile=dengan permission600. - Tambahkan pengerasan ringan:
NoNewPrivileges=yes,PrivateTmp=yes, danProtectSystem=strictbila service tidak perlu menulis ke sistem. - Untuk service yang hanya butuh satu proses sederhana,
DynamicUser=yesbisa membuat user otomatis tanpa kamu mengelola akun. - Etika: membuat service di komputer lab sekolah untuk menjalankan program yang bukan tugasmu, termasuk pelanggaran. Kamu diberi akses root untuk belajar, bukan untuk menguasai mesin.
π Angka penting: Nama unit maksimal 255 karakter, dan hanya boleh berisi huruf, angka, titik, garis bawah, tanda hubung, titik dua, dan backslash. Spasi diganti dengan aturan escaping tersendiri; pakai systemd-escape kalau ragu.
π Kesimpulan
Service bukan sihir dan bukan program yang lebih pintar. Service adalah kontrak: kamu menyebut program, user, folder, dan aturan restart; systemd yang mengawasi sisanya.
Tiga hal yang paling menentukan berhasil atau tidaknya service buatanmu: ExecStart absolut, User= dan WorkingDirectory= yang benar, serta daemon-reload setelah setiap perubahan. Sisanya hanya latihan membaca status dan log.
Langkah berikutnya: ambil satu skrip yang biasa kamu jalankan manual di lab, lalu ubah menjadi service dengan Type=oneshot. Rasakan bedanya setelah kamu reboot server dan skrip itu berjalan sendiri.
π Materi terkait
- Linux : Cara Membaca Penyebab Service Gagal Start dengan systemctl status dan journalctl β lanjutan wajib setelah artikel ini, untuk membaca kegagalan service.
- Linux : Cek Service yang Sedang Berjalan β memeriksa service lain yang sudah aktif di server.
- Linux : Manajemen Paket dan Repositori Debian β tempat paket resmi memasang unit
.servicemiliknya. - Linux : Manajemen User Dasar β dasar membuat user sistem untuk
User=. - Linux : Permission File dan Folder β kenapa skrip
755dan log600penting. - Linux: Cron Job β alternatif untuk tugas terjadwal yang tidak perlu hidup terus.
- Linux : Praktikum Audit Repositori dan Diagnosa Instalasi Paket Gagal β pola diagnosis lapis demi lapis yang bisa kamu pakai untuk service.
π Referensi
- systemd.service(5) β Debian bookworm β tipe service,
ExecStart,Restart,RestartSec, perilakuType=simple. - systemd.unit(5) β Debian bookworm β urutan pencarian folder unit, drop-in, symlink
.wants/, aturan nama unit. - systemd.exec(5) β Debian bookworm β
User=,Group=,WorkingDirectory=, dan pengerasan proses. - systemctl(1) β Debian bookworm β
start,enable,daemon-reload,reset-failed,edit,cat. - journalctl(1) β Debian bookworm β membaca log per unit dan per boot.
- systemd-analyze(1) β Debian bookworm β
verifyuntuk memeriksa unit sebelum dijalankan.