Aplikasi web butuh database, database butuh penyimpanan, dan semuanya butuh jaringan — tidak ada service yang benar-benar hidup sendirian. Pada init klasik urutan ini diatur dengan angka pada nama script; systemd menggantinya dengan deklarasi dependensi langsung di unit file. Kita sudah melihat sepenggal Requires=dbus.socket di Chapter systemd Units
; sekarang saatnya membedahnya penuh. Kuncinya satu: systemd memisahkan dua pertanyaan yang berbeda — apa yang ikut dinyalakan dan siapa yang menyala lebih dulu — dan keduanya punya directive masing-masing.
Dua Pertanyaan Berbeda: Menarik dan Mengurutkan #
Directive dependensi terbagi dua keluarga. Keluarga requirement menjawab: bila unit A dinyalakan, unit mana yang ikut ditarik? Keluarga ordering menjawab: bila A dan B sama-sama dinyalakan, mana yang lebih dulu? Keduanya independen — directive requirement tidak mengatur urutan, directive ordering tidak menarik apa pun.
Wants dan Requires: Relasi Lunak dan Keras #
Dua directive requirement yang paling sering dipakai, dengan konsekuensi gagal yang berbeda:
| Directive | Bila target ikut ditarik dan gagal | Bila target dihentikan eksplisit |
|---|---|---|
Wants= | unit pengingat tetap berjalan | unit pengingat tetap berjalan |
Requires= | unit pengingat ikut gagal start | unit pengingat ikut dihentikan |
Wants= adalah hubungan longgar: “coba nyalakan itu, tapi tidak apa-apa bila gagal”. Requires= adalah hubungan keras: “tanpa itu, saya menolak hidup”. Praktik umum: Wants untuk dependensi yang tidak fatal — misalnya sinkronisasi waktu — dan Requires untuk yang wajib. Mari kita lihat keduanya dalam satu unit:
cat > webapp.service << 'EOF'
[Unit]
Description=Aplikasi web yang butuh jaringan
Wants=network-online.target
Requires=network.target
After=network.target network-online.target
[Service]
ExecStart=/usr/bin/python3 -m http.server 8080
[Install]
WantedBy=multi-user.target
EOF
systemd-analyze verify webapp.service && echo "sintaks unit valid"Output yang Dihasilkan:
sintaks unit validMari kita telaah blok di atas:
- Baris 3-4 (
Wants=danRequires=): saatwebapp.servicedinyalakan, kedua target jaringan ikut ditarik. Bilanetwork-online.targetgagal, webapp tetap jalan; bilanetwork.targetgagal, webapp ikut gagal — aplikasi web tanpa jaringan memang tidak masuk akal. - Baris 5 (
After=): hanya mengurutkan — webapp menunggu kedua target selesai dinyalakan lebih dulu. Baris ini tidak menarik apa pun; tugas menarik sudah dipegang baris 3-4. - Baris 11 (
WantedBy=multi-user.target): kebalikan dari kedua directive di atas — bukan webapp yang menarik, melainkan webapp yang menawarkan diri ditarik oleh target saat boot.
After dan Before: Urutan, Bukan Dependensi #
Poin baris 5 layak ditegaskan terpisah karena inilah salah kaprah paling umum pemula systemd:
Unit bawaan sistem adalah contoh terbaik pola “pasangan Wants + After” — misalnya service manajemen login:
grep -E '^(Wants|After)=' /lib/systemd/system/systemd-logind.serviceOutput yang Dihasilkan:
Wants=user.slice [email protected]
After=nss-user-lookup.target user.slice [email protected]
Wants=dbus.socket
After=dbus.socketEmpat baris itu adalah dua pasangan. Pasangan pertama menarik user.slice dan driver grafis, lalu After= berisi sama memastikan keduanya siap lebih dulu; pasangan kedua, Wants=dbus.socket plus After=dbus.socket, adalah pola idiomatik yang sering kita temui: nyalakan dependensinya, lalu tunggu sampai benar-benar siap.
BindsTo, PartOf, dan Conflicts #
Tiga directive lain melengkapi kasus khusus. BindsTo= versi paling keras dari Requires: unit ini ikut mati begitu targetnya berhenti karena alasan apa pun. PartOf= menularkan perubahan: target di-restart atau di-stop, unit yang menyatakan PartOf ikut — dipakai agar container ikut bangkit saat engine-nya di-restart. Conflicts= hubungan bermusuhan: unit ini dan targetnya tidak boleh aktif bersamaan. Rangkaian directive lengkapnya dengan contoh sintaks dirangkum di systemd.unit(5)
.
Target: Kumpulan yang Menarik Anggotanya #
Semua relasi di atas bertemu pada satu jenis unit: target. Target tidak menjalankan proses apa pun — isinya murni deklarasi dependensi, titik temu tempat puluhan unit mengikat diri. Perhatikan isi multi-user.target, target utama mode teks pada server:
grep -v '^#' /lib/systemd/system/multi-user.target | grep -v '^$'Output yang Dihasilkan:
[Unit]
Description=Multi-User System
Documentation=man:systemd.special(7)
Requires=basic.target
Conflicts=rescue.service rescue.target
After=basic.target rescue.service rescue.target
AllowIsolate=yesMari kita baca isinya:
Requires=basic.target+After=basic.target: pola Wants-plus-After yang sama, kini dipakai target sendiri — multi-user menarik fondasi sistem lalu menunggunya.Conflicts=rescue.service rescue.target: mode multi-user dan mode penyelamatan saling meniadakan — inilah yang menjalankan pergantian mode saatsystemctl isolatedari Chapter systemctl .AllowIsolate=yes: izin agar target ini boleh dijadikan tujuanisolate— mematikan semua unit di luar rantainya.- Tidak ada section
[Service]: bukti bahwa target memang murni deklarasi — tidak ada proses yang dijalankan.
Anggota target datang dari dua arah: ditarik oleh Requires/Wants, atau menawarkan diri lewat WantedBy — mekanisme symlink .wants dari Chapter Managing Services
.
Transaksi: Perubahan yang Atomik #
Saat kita menjalankan systemctl start webapp.service, systemd tidak bekerja satu-satu. systemd menyusun transaction: kumpulan job untuk semua unit yang ditarik, dicek siklus urutannya, lalu dieksekusi sebagai satu kesatuan. Bila ditemukan masalah — misalnya dua unit saling menunggu lewat After= yang berlawanan arah — perintah ditolak dengan pesan ordering cycle found dan tidak ada job yang berjalan. Desain atomik ini menjaga sistem tidak setengah jalan: lebih baik menolak perintah daripada membiarkan service menyala dengan dependensi yang tidak jelas.
Peta dependensi kita tinggal satu yang belum dijelajahi: target sebagai pengganti runlevel klasik — bedanya multi-user dan graphical, dan cara default target ditentukan saat boot. Itulah topik Chapter systemd Targets
.