SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor

systemd vs systemctl: Arahan Urus Servis Linux

systemd ialah pengurus servis, systemctl ialah arahan untuk mengawalnya. Cuba start, enable dan mask pada unit demo, dan lihat apa yang kekal selepas reboot.

Soalan systemd vs systemctl ada jawapan yang pendek. systemd ialah sistem init dan pengurus servis yang berjalan sebagai PID 1, iaitu proses pertama yang dimulakan oleh kernel Linux semasa boot. systemctl pula ialah arahan yang anda taip untuk bercakap dengan systemd, sama ada untuk memulakan servis, menghentikannya, mengaktifkannya semasa boot atau melihat keadaannya.

Jadi anda tidak perlu memilih antara kedua-duanya. systemd melakukan kerja, dan systemctl ialah alat kawalannya. Semua arahan di bawah menyasarkan satu unit demo yang dibina daripada coreutils sahaja. Tiada pakej perlu dipasang, dan tiada servis sebenar di VPS anda akan terganggu. Di bahagian akhir, unit demo itu dibuang semula.

Apakah beza systemd dan systemctl?

Apabila VPS anda boot, kernel memulakan satu proses sahaja. Proses itu ialah systemd, dan semua proses lain bermula di bawahnya. Semak sendiri:

ps -p 1 -o comm=

Pada Ubuntu 24.04, arahan ini mencetak systemd.

systemd mengurus unit. Unit ialah fail konfigurasi yang menerangkan satu perkara untuk diurus. Unit servis berakhir dengan .service. Ada jenis lain, seperti .timer untuk kerja berjadual dan .target untuk kumpulan unit. Target mewakili satu keadaan sistem, contohnya multi-user.target untuk pelayan biasa tanpa desktop. Jika anda biasa dengan runlevel lama, baca perbandingan target systemd dengan runlevel.

systemctl tidak menjalankan servis dengan sendirinya. Ia menghantar permintaan kepada systemd melalui D-Bus (saluran mesej antara proses di Linux), dan systemd yang memulakan atau menghentikan proses. Sebab itu systemctl boleh melaporkan keadaan servis yang dimulakan semasa boot, walaupun anda tidak pernah memulakannya sendiri. Untuk latar belakang mengapa Linux beralih kepada model ini, lihat sejarah systemd dan sebab ia menggantikan skrip init lama.

Satu peraturan ringkas tentang sudo. Arahan yang mengubah keadaan (start, stop, enable, mask) memerlukan sudo. Arahan yang hanya membaca (status, is-active, cat, list-units) boleh dijalankan sebagai pengguna biasa.

Bina unit demo yang selamat untuk berlatih

Unit demo ini menjalankan sleep infinity. Arahan itu tidur tanpa had masa dan hampir tidak menggunakan CPU, jadi systemd ada satu proses yang berjalan lama untuk diurus. sleep datang daripada coreutils, yang sudah ada pada setiap pelayan Ubuntu.

sudo mkdir -p /usr/local/lib/systemd/system
sudo tee /usr/local/lib/systemd/system/demo.service > /dev/null <<'EOF'
[Unit]
Description=Unit demo untuk belajar systemctl

[Service]
ExecStart=/usr/bin/sleep infinity

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload

Setiap bahagian fail ada tugas sendiri:

  • [Unit] menyimpan maklumat umum. Description ialah teks yang dipaparkan oleh systemctl status.
  • [Service] menerangkan proses. ExecStart mesti menggunakan laluan penuh ke program. Tiada baris Type=, jadi systemd menggunakan nilai lalai simple. Untuk pilihan lain, baca penerangan jenis Type= dalam unit servis.
  • [Install] hanya dibaca oleh enable dan disable. WantedBy=multi-user.target memberitahu enable di mana pautan perlu diletakkan. Unit tanpa bahagian ini tidak boleh di-enable.

Mengapa fail ini berada di /usr/local/lib/systemd/system dan bukan di /etc/systemd/system? systemd membaca unit daripada beberapa direktori. Fail di /etc/systemd/system mengatasi fail dengan nama yang sama di direktori lain. Pakej Ubuntu memasang unit mereka di /usr/lib/systemd/system, dan /usr/local/lib/systemd/system ialah tempat yang setara untuk unit yang anda pasang sendiri.

Arahan mask, yang anda akan cuba nanti, berfungsi dengan meletakkan pautan bernama demo.service di /etc/systemd/system. Jika fail demo anda sendiri sudah berada di laluan itu, tiada tempat untuk pautan tersebut. Dengan meletakkan demo di luar /etc, ia berkelakuan seperti servis daripada pakej, dan setiap arahan di bawah boleh dicuba padanya.

daemon-reload di hujung blok itu penting. systemd membaca fail unit ke dalam memori. Fail baharu atau fail yang diubah tidak dilihat sehingga anda menyuruhnya membaca semula.

Semak bahawa systemd sudah mengenali unit itu:

systemctl status demo --no-pager

Baris Loaded: patut menunjukkan laluan /usr/local/lib/systemd/system/demo.service. Jika ia menyebut not-found, sama ada nama fail salah atau daemon-reload belum dijalankan.

start, stop dan restart: kawal proses sekarang

sudo systemctl start demo
systemctl show -p MainPID demo
sudo systemctl restart demo
systemctl show -p MainPID demo
sudo systemctl stop demo
systemctl show -p MainPID demo

Akhiran .service boleh ditinggalkan, jadi demo dan demo.service merujuk kepada unit yang sama.

start menjalankan ExecStart sekarang. Ia tidak mengubah apa yang berlaku semasa boot. systemctl show -p MainPID mencetak satu baris seperti MainPID=1234, iaitu ID proses utama servis itu. Nombor selepas restart berbeza daripada nombor sebelumnya, kerana restart menghentikan proses lama dan memulakan proses baharu. Selepas stop, nilainya menjadi MainPID=0, kerana tiada proses lagi.

Ada juga systemctl reload. Ia meminta servis membaca semula konfigurasinya tanpa berhenti, tetapi hanya untuk unit yang mempunyai baris ExecReload. Unit demo tidak mempunyai baris itu, jadi reload akan gagal padanya.

Baca status dan log dengan --no-pager

systemctl status demo --no-pager
journalctl -u demo --no-pager -n 20

Secara lalai, systemctl dan journalctl menghantar output yang panjang kepada pager (program less), yang menunggu sehingga anda menekan q. --no-pager mencetak semuanya terus ke terminal dan kembali ke prompt. Ini lebih sesuai untuk skrip dan untuk menyalin output ke dalam tiket sokongan.

Dalam output status, baris yang paling berguna ialah:

  • Loaded: menunjukkan fail unit yang digunakan, dan sama ada unit itu enabled atau disabled.
  • Active: menunjukkan keadaan sekarang dan sejak bila.
  • Main PID: menunjukkan ID proses utama, jika ia sedang berjalan.
  • Baris log di bawah sekali ialah beberapa mesej terakhir daripada journal untuk unit ini.

journalctl -u demo menapis journal kepada unit demo sahaja, dan -n 20 mengehadkan output kepada 20 baris terakhir. Apa yang tercatat bergantung pada arahan yang anda sudah jalankan, jadi bacalah baris itu sendiri. Apabila servis sebenar gagal, dua arahan ini ialah langkah pertama. Langkah seterusnya ialah membaca kod keluar apabila unit systemd tidak mahu bermula.

is-active dan is-enabled: semak keadaan sebelum dan selepas enable --now

Dua arahan ini menjawab dua soalan yang berbeza. is-active bertanya: adakah unit sedang berjalan sekarang? is-enabled bertanya: adakah unit akan bermula semasa boot?

Unit demo sudah dihentikan dan belum pernah di-enable. Jalankan:

systemctl is-active demo; echo "kod keluar: $?"
systemctl is-enabled demo; echo "kod keluar: $?"

Setiap arahan mencetak satu perkataan yang menerangkan keadaan unit. Kemudian echo $? mencetak kod keluar (exit code) arahan itu. Catat perkataan dan nombor yang anda lihat. Kod keluar 0 bermaksud "ya". Nombor lain bermaksud "tidak". Pada peringkat ini, kedua-dua kod keluar sepatutnya bukan sifar, kerana unit itu tidak berjalan dan tidak enabled.

Kod keluar inilah yang penting untuk skrip. Shell tidak membaca perkataan yang dicetak. Ia hanya melihat sama ada kod keluar sifar atau tidak.

Sekarang aktifkan dan mulakan unit dalam satu langkah:

sudo systemctl enable --now demo
ls -l /etc/systemd/system/multi-user.target.wants/demo.service

enable sendiri tidak memulakan apa-apa. Ia mencipta pautan simbolik (symlink) di /etc/systemd/system/multi-user.target.wants/ yang menunjuk ke fail unit anda. Semasa boot, systemd memulakan multi-user.target, melihat pautan itu, lalu memulakan demo.service juga. Pilihan --now menambah start serta-merta, jadi anda tidak perlu menunggu reboot. Arahan ls -l menunjukkan pautan yang baru dicipta.

Jalankan semula dua semakan tadi:

systemctl is-active demo; echo "kod keluar: $?"
systemctl is-enabled demo; echo "kod keluar: $?"

Kini kedua-dua kod keluar sepatutnya 0. Bandingkan perkataan yang dicetak dengan catatan anda sebelum ini.

Untuk semakan dalam satu baris, tambah --quiet. Pilihan ini menyembunyikan perkataan dan hanya meninggalkan kod keluar:

systemctl is-active --quiet demo && systemctl is-enabled --quiet demo && echo "demo OK: sedang berjalan dan akan bermula semasa boot"

&& hanya menjalankan arahan seterusnya jika arahan sebelumnya keluar dengan 0. Jadi mesej itu hanya muncul apabila kedua-dua syarat benar. Jika salah satu gagal, tiada apa-apa dicetak. Baris seperti ini sesuai untuk skrip pemantauan ringkas, dan anda boleh menjalankannya mengikut jadual dengan servis dan timer systemd di VPS.

stop, disable atau mask: yang mana kekal selepas reboot?

Tiga arahan ini kelihatan serupa, tetapi kesannya berbeza:

  • stop menghentikan proses sekarang. Ia tidak kekal selepas reboot. Jika unit itu enabled, systemd memulakannya semula pada boot seterusnya.
  • disable membuang pautan di bawah multi-user.target.wants. Ia kekal selepas reboot, jadi unit tidak lagi bermula secara automatik. Tetapi disable tidak menghentikan proses yang sedang berjalan, dan unit itu masih boleh dimulakan secara manual atau oleh unit lain yang memerlukannya.
  • mask menghalang unit daripada dimulakan dengan apa cara sekalipun. Ia juga kekal selepas reboot.

Ringkasnya, hanya disable dan mask kekal selepas reboot. stop sahaja tidak. Untuk menghentikan servis sekarang dan juga semasa boot, gunakan sudo systemctl disable --now nama-servis.

Jika anda menggunakan Docker Compose, anda mungkin sudah bertemu soalan yang sama dalam bentuk lain: beza docker compose stop dan docker compose down. docker compose stop menghentikan kontena, tetapi kontena itu masih wujud. docker compose down menghentikan dan membuang kontena serta rangkaian projek itu. Di peringkat hos, systemctl ada pembahagian yang serupa: stop ialah tindakan sementara, manakala disable dan mask mengubah apa yang berlaku semasa boot. Bezanya, systemctl tidak pernah memadam fail unit anda. Bagi kontena yang perlu hidup semula selepas reboot, lihat cara memastikan Docker Compose bermula semasa boot.

Cuba disable pada unit demo:

sudo systemctl disable demo
systemctl is-active demo; echo "kod keluar: $?"
systemctl is-enabled demo; echo "kod keluar: $?"

Kod keluar is-active masih 0, kerana disable tidak menyentuh proses yang sedang berjalan. Kod keluar is-enabled kini bukan sifar, kerana pautan untuk boot sudah dibuang.

mask dan unmask: sekat servis sepenuhnya

sudo systemctl mask --now demo
ls -l /etc/systemd/system/demo.service
sudo systemctl start demo

mask mencipta pautan /etc/systemd/system/demo.service yang menunjuk ke /dev/null. Oleh sebab /etc/systemd/system mengatasi /usr/local/lib/systemd/system, systemd kini melihat unit kosong di tempat unit sebenar, jadi ia enggan memulakannya. --now turut menghentikan proses yang sedang berjalan. Tanpa --now, proses itu terus berjalan sehingga ia berhenti sendiri.

Arahan start terakhir itu sepatutnya gagal, dan mesej ralatnya menyatakan bahawa unit itu masked. Itulah tujuan mask. Gunakannya untuk servis daripada pakej yang anda tidak mahu langsung berjalan, termasuk apabila servis lain cuba memulakannya sebagai kebergantungan (dependency).

Untuk membatalkan sekatan:

sudo systemctl unmask demo
systemctl is-enabled demo; echo "kod keluar: $?"

unmask hanya membuang pautan ke /dev/null. Ia tidak memulakan servis dan tidak meng-enable-nya.

Ubah fail unit: cat, daemon-reload dan edit

Sebelum mengubah unit, lihat apa yang systemd sebenarnya gunakan:

systemctl cat demo

systemctl cat mencetak fail unit bersama sebarang fail drop-in. Setiap bahagian bermula dengan baris komen yang menunjukkan laluan fail. Ini cara paling cepat untuk tahu fail mana yang berkuat kuasa.

Sekarang ubah Description terus dalam fail, kemudian lihat apa yang berlaku sebelum dan selepas daemon-reload:

sudo sed -i 's/^Description=.*/Description=Unit demo versi kedua/' /usr/local/lib/systemd/system/demo.service
systemctl status demo --no-pager
sudo systemctl daemon-reload
systemctl status demo --no-pager

Status pertama masih memaparkan penerangan lama, bersama amaran bahawa fail unit berubah di cakera dan anda perlu menjalankan daemon-reload. Ini berlaku kerana systemd masih menggunakan salinan dalam memori. Selepas daemon-reload, status memaparkan penerangan baharu.

Satu perkara yang sering terlepas: daemon-reload hanya mengemas kini konfigurasi dalam memori. Proses yang sedang berjalan tidak dimulakan semula. Jika anda mengubah ExecStart atau tetapan lain untuk servis yang sedang berjalan, jalankan daemon-reload dan kemudian restart.

Untuk unit daripada pakej, jangan ubah fail di /usr/lib/systemd/system, kerana kemas kini pakej akan menulis gantinya. Gunakan sudo systemctl edit nama-servis. Arahan ini membuka editor teks, jadi jalankannya sendiri dalam terminal interaktif dan bukan dalam skrip. Selepas anda keluar dari editor, semak hasilnya dengan systemctl cat nama-servis. Fail drop-in ialah tempat biasa untuk menambah tetapan seperti dalam pengasingan servis dengan ProtectSystem dan PrivateTmp.

Cari servis yang gagal dan senaraikan fail unit

systemctl list-units --type=service --state=failed --no-pager
systemctl list-unit-files --type=service --no-pager
systemctl list-unit-files 'demo*' --no-pager

list-units menyenaraikan unit yang sudah dimuatkan ke dalam memori systemd. Dengan --state=failed, ia hanya menunjukkan servis yang gagal. Pada pelayan yang sihat, senarai ini kosong. Jalankan arahan ini selepas setiap reboot dan selepas setiap kemas kini besar.

list-unit-files pula menyenaraikan fail unit di cakera bersama keadaan enable masing-masing, termasuk unit yang belum pernah dimulakan. Lajur keadaan menunjukkan nilai seperti enabled, disabled, static atau masked. static bermaksud unit itu tiada bahagian [Install], jadi ia tidak boleh di-enable dan hanya dimulakan oleh unit lain. Corak 'demo*' mengehadkan senarai kepada unit yang namanya bermula dengan demo. Letakkan corak dalam tanda petikan supaya shell tidak cuba mengembangkannya.

Buang unit demo

Apabila selesai berlatih, kembalikan pelayan kepada keadaan asal:

sudo systemctl disable --now demo
sudo rm /usr/local/lib/systemd/system/demo.service
sudo systemctl daemon-reload
systemctl list-unit-files 'demo*' --no-pager

disable --now memastikan tiada proses dan tiada pautan boot yang tertinggal, walaupun anda melangkau beberapa langkah di atas. rm membuang fail unit, dan daemon-reload membuat systemd melupakannya. Arahan terakhir sepatutnya tidak menyenaraikan sebarang unit demo. Direktori /usr/local/lib/systemd/system boleh dibiarkan, kerana direktori kosong tidak menjejaskan apa-apa.

Senarai ringkas arahan systemctl

  • sudo systemctl start nama dan sudo systemctl stop nama: mula atau henti sekarang sahaja.
  • sudo systemctl restart nama: henti dan mula semula, dengan PID baharu.
  • sudo systemctl enable --now nama: mula sekarang dan setiap kali boot.
  • sudo systemctl disable --now nama: henti sekarang dan jangan mula semasa boot.
  • sudo systemctl mask --now nama dan sudo systemctl unmask nama: sekat sepenuhnya, atau buang sekatan.
  • systemctl status nama --no-pager: keadaan semasa dan log terakhir.
  • systemctl is-active --quiet nama dan systemctl is-enabled --quiet nama: semakan untuk skrip melalui kod keluar.
  • systemctl list-units --type=service --state=failed: servis yang gagal.
  • systemctl cat nama: fail unit yang sedang berkuat kuasa.
  • sudo systemctl daemon-reload: baca semula fail unit selepas diubah.

FAQ

Apakah beza systemd dan systemctl?

systemd ialah sistem init dan pengurus servis. Ia berjalan sebagai PID 1, iaitu proses pertama selepas kernel, dan ia memulakan serta mengawasi semua servis lain. systemctl ialah arahan baris perintah untuk menghantar permintaan kepada systemd, contohnya systemctl start, systemctl enable atau systemctl status. Anda tidak memasang salah satu sahaja, kerana systemctl datang bersama systemd.

Mengapa servis saya hidup semula selepas reboot walaupun saya sudah stop?

systemctl stop hanya menghentikan proses sekarang. Jika servis itu enabled, pautan di bawah multi-user.target.wants masih ada, jadi systemd memulakannya semula semasa boot. Gunakan sudo systemctl disable --now nama-servis untuk menghentikannya sekarang dan juga semasa boot. Jika servis lain masih memulakannya sebagai kebergantungan, gunakan sudo systemctl mask --now nama-servis.

Bilakah saya perlu menjalankan systemctl daemon-reload?

Jalankan sudo systemctl daemon-reload setiap kali anda mencipta atau mengubah fail unit dengan tangan, dan juga selepas memadamnya. systemd menyimpan unit dalam memori, jadi tanpa reload ia masih menggunakan versi lama, dan systemctl status akan memberi amaran bahawa fail berubah di cakera. Reload tidak memulakan semula servis yang sedang berjalan, jadi ikuti dengan restart jika perubahan menyentuh proses itu.

Bagaimana saya tahu servis mana yang gagal di VPS saya?

Jalankan systemctl list-units --type=service --state=failed --no-pager. Pada pelayan yang sihat, senarai ini kosong. Untuk setiap servis yang tersenarai, baca systemctl status nama-servis --no-pager dan journalctl -u nama-servis --no-pager -n 20 untuk melihat mesej terakhir sebelum ia gagal.

Apakah maksud kod keluar systemctl is-active dan is-enabled?

Kod keluar 0 bermaksud ya: unit sedang berjalan untuk is-active, atau unit enabled untuk is-enabled. Nombor selain sifar bermaksud tidak. Perkataan yang dicetak menerangkan keadaan untuk manusia, tetapi skrip patut bergantung pada kod keluar. Tambah --quiet untuk menyembunyikan perkataan itu, contohnya systemctl is-active --quiet nama-servis && echo berjalan.