Kembali ke blog

Systemd Service Tidak Berjalan? Begini Cara Memperbaikinya

14 September 2026

Layanan systemd yang tidak mau berjalan hampir tidak pernah misterius. Jalankan systemctl status <unit>, lalu baca 50 baris journal terakhir untuk unit itu dengan journalctl -u <unit> -n 50 --no-pager — dari keduanya, satu dari lima penyebab biasanya sudah disebutkan langsung: path yang salah, binary yang hilang, izin yang keliru, penolakan SELinux/AppArmor, atau galat sintaks unit file. Alasan kegagalannya ada di log; perbaikan-perbaikan di bawah hanyalah pencocokan pola terhadap log itu.

Bagaimana melihat kenapa layanan systemd gagal?

Status dulu, journal kemudian:

systemctl status myapp.service
journalctl -u myapp.service -n 50 --no-pager

status memberi Anda kondisi (inactive (dead), failed (exit-code), activating (auto-restart)) dan beberapa baris log terakhir. Journal memberi Anda keseluruhan cerita: stdout, stderr, dan keluhan systemd sendiri tentang unit itu.

Jika unit pernah gagal sebelumnya dan Anda ingin rekaman run itu, tambahkan -b untuk boot saat ini atau --since today:

journalctl -u myapp.service -b --no-pager

Untuk perangkat lengkapnya — boot, prioritas, mengikuti output secara live — lihat memo journalctl. Memori ototnya sama.

Satu pasang lagi yang layak diketahui:

systemctl list-units --failed
systemctl reset-failed myapp.service

Yang pertama mendaftar setiap unit merah di mesin. Yang kedua membersihkan status failed setelah Anda memperbaikinya — kosmetik, tetapi mencegah halaman status berteriak serigala.

Apa saja penyebab yang paling umum?

Setelah log menyebutkan gejalanya, penyebabnya hampir selalu salah satu dari lima ini:

Kata logPenyebab yang mungkinPerbaikan
status=203/EXECPath ExecStart= salah atau interpreter hilangPath absolut, chmod +x, periksa shebang
status=203/EXEC pada skripSkrip berakhiran baris CRLF atau shebang salahdos2unix script.sh, perbaiki baris pertama
status=1/FAILURE, tanpa log aplikasiWorking directory atau env var hilangSet WorkingDirectory=, tambah Environment=
Permission deniedPengguna tak bisa membaca file atau bind portPerbaiki kepemilikan; port di bawah 1024 butuh AmbientCapabilities=CAP_NET_BIND_SERVICE atau root
Unit is maskedSeseorang menjalankan systemctl masksystemctl unmask myapp.service
Edit unit file “tidak berefek”Daemon tidak di-reloadsystemctl daemon-reload

Keluarga 203/EXEC layak disebut khusus karena dialah yang memakan sore Anda. Systemd tidak memakai shell Anda untuk menjalankan ExecStart=. Artinya:

# Salah — tanpa shell, ~ tidak pernah mengembang, tanpa pencarian PATH
ExecStart=~/app/run.sh

# Benar
ExecStart=/opt/app/run.sh

Dan skripnya sendiri harus executable dan diawali shebang sungguhan (#!/bin/bash atau #!/usr/bin/env bash). Skrip yang jalan mulus dari terminal Anda tetapi gagal dengan 203 di bawah systemd hampir selalu salah satu dari: tidak executable, akhiran baris CRLF, shebang yang menunjuk ke tempat tak ada, atau path relatif.

Kenapa bisa jalan saat dijalankan manual tetapi tidak saat boot?

Ini bug urutan klasik. Jika log menunjukkan kegagalan tepat setelah boot tetapi unitnya jalan mulus saat Anda menjalankan systemctl start dengan tangan, layanan Anda kalah balapan — ia mengincar jaringan, disk yang di-mount, atau database sebelum hal itu ada.

Perbaikannya adalah mendeklarasikan dependensi alih-alih berharap:

[Unit]
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
ExecStartPre=/usr/bin/test -f /opt/app/config.toml

After= mengurutkan start; Wants= membuat systemd benar-benar menaikkan dependensinya. network-online.target hanya bekerja jika service network-wait diaktifkan di distro Anda, jadi periksa systemctl is-enabled NetworkManager-wait-online.service (atau padanan systemd-networkd). Gerbang ExecStartPre= adalah cara yang murah dan jujur untuk gagal dengan lantang beserta pesan yang terbaca, bukan stack trace.

Varian keduanya: service jalan saat boot tetapi langsung mati. Cari hal-hal yang dimiliki lingkungan interaktif Anda tetapi tidak dimiliki boot — perbedaan PATH, virtualenv, HOME. Set yang Anda butuhkan secara eksplisit:

[Service]
Environment="PATH=/opt/app/venv/bin:/usr/bin"
User=appuser
WorkingDirectory=/opt/app

Kenapa layanan saya tidak mencatat log ke journal?

Jika journalctl -u tidak menampilkan apa pun, periksa tiga hal secara berurutan:

  1. StandardOutput= dan StandardError= di unit — keduanya harus journal (default) atau journal+console. Bisa jadi seseorang menyetelnya ke null.
  2. Aplikasi menulis ke file, bukan ke stdout. Systemd hanya menangkap stdout/stderr; penulis log-file melewati journal sepenuhnya. Arahkan aplikasinya ke stdout, atau bacalah filenya.
  3. Batas penyimpanan membuang baris lama: journalctl --disk-usage, dan SystemMaxUse= di /etc/systemd/journald.conf jika journal sedang tersedak.

Untuk debug proses start-nya sendiri, tak ada yang mengalahkan menjatuhkan shell ke dalam konteks boot:

[Service]
ExecStart=/bin/bash -c 'exec /opt/app/bin/server 2>&1'

Atau, untuk misteri yang sesungguhnya, jalankan perintah ExecStart= persisnya sebagai pengguna unit tersebut di dalam shell — sebagian besar perbedaan lingkungan muncul dalam sepuluh detik pertama.

Bagaimana membuatnya restart otomatis setelah crash?

Kebijakan defaultnya Restart=no: service yang crash tetap mati, dan Anda mengetahuinya dari seorang pengguna. Perbaiki per service:

[Service]
Restart=on-failure
RestartSec=5
SetelanRestart saat
no (default)Tidak pernah
on-failureExit non-nol, signal, timeout
alwaysExit apa pun, bahkan yang bersih
on-watchdogHanya timeout watchdog

Padukan Restart=on-failure dengan penjaga laju start agar loop crash tidak menghantam mesin: StartLimitIntervalSec= dan StartLimitBurst= di bagian [Unit]. Lima kegagalan dalam enam puluh detik seharusnya memanggil manusia, bukan memutar CPU.

Jika Anda merangkai ini sebagai job terjadwal alih-alih daemon, timbang dulu cron vs timer systemd — timer memberi Anda logging journal dan pengurutan dependensi secara gratis, dan justru itulah yang terus dicari-cari artikel ini.

Checklist 60 detik

  1. systemctl status <unit> — baca kondisi dan baris-baris terakhir.
  2. journalctl -u <unit> -n 50 --no-pager — temukan error yang sebenarnya.
  3. 203/EXEC? Perbaiki path, shebang, izin. Permission denied? Perbaiki pengguna dan kepemilikan file.
  4. Gagal hanya saat boot? Tambahkan After=/Wants=network-online.target dan gerbang ExecStartPre=.
  5. Mengubah unit file? systemctl daemon-reload && systemctl restart <unit>.
  6. Tambahkan Restart=on-failure agar crash berikutnya mengumumkan dirinya alih-alih bersembunyi.

Sebagian besar momen “systemd itu rumit” berujung pada satu hal: errornya dari awal memang ada di journal. Bacalah sebelum mengedit unit file, bukan sesudahnya.

— mrsaynothing

Get the next one by email

One email per post. No spam, no algorithms.

self-hosted · no third parties · one-click unsubscribe

what is this?

Kuantisasi GGUF: Level Mana yang Harus Anda Pakai?

Suka tulisannya? Saya membangun seperti ini untuk hidup. pekerjakan saya