metodologi generik untuk men-debug siklus pemesanan dalam systemd

23

Saya menyadari mengikuti utas dan seharusnya jawaban untuknya . Kecuali jawaban bukanlah jawaban dalam arti umum. Ini menceritakan apa masalahnya dalam satu kasus tertentu, tetapi tidak secara umum.

Pertanyaan saya adalah: apakah ada cara untuk men-debug siklus pemesanan dengan cara yang umum ? Misalnya: apakah ada perintah yang akan menggambarkan siklus dan apa yang menghubungkan satu unit ke unit lainnya?

Sebagai contoh, saya telah mengikuti journalctl -b(tolong abaikan tanggal, sistem saya tidak memiliki RTC untuk menyinkronkan waktu dengan):

Jan 01 00:00:07 host0 systemd[1]: Found ordering cycle on sysinit.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on local-fs.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on cvol.service/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on basic.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on sockets.target/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on dbus.socket/start
Jan 01 00:00:07 host0 systemd[1]: Found dependency on sysinit.target/start
Jan 01 00:00:07 host0 systemd[1]: Breaking ordering cycle by deleting job local-fs.target/start
Jan 01 00:00:07 host0 systemd[1]: Job local-fs.target/start deleted to break ordering cycle starting with sysinit.target/start

di mana cvol.service (yang diperkenalkan, dan yang memutus siklus) adalah:

[Unit]
Description=Mount Crypto Volume
After=boot.mount
Before=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=no
ExecStart=/usr/bin/cryptsetup open /dev/*** cvol --key-file /boot/***

[Install]
WantedBy=home.mount
WantedBy=root.mount
WantedBy=usr-local.mount

Menurut journalctl, cvol.service menginginkan basic.service, kecuali itu tidak, setidaknya tidak jelas. Apakah ada perintah yang akan menunjukkan dari mana tautan ini berasal? Dan secara umum, apakah ada perintah, yang akan menemukan siklus dan menunjukkan di mana setiap tautan dalam siklus berasal?

galet
sumber

Jawaban:

20

Apakah ada perintah yang akan menunjukkan dari mana tautan ini berasal?

Yang terdekat yang dapat Anda lakukan adalah systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After cvol.service, yang akan menampilkan daftar dependensi (efektif) yang dihasilkan untuk unit tertentu.

apakah ada perintah, yang akan menemukan siklus dan menunjukkan di mana setiap tautan dalam siklus berasal?

Setahu saya, tidak ada perintah seperti itu. Sebenarnya systemd tidak menawarkan apa pun untuk membantu debugging siklus pemesanan (mendesah).

Menurut journalctl, cvol.service menginginkan basic.service, kecuali itu tidak, setidaknya tidak jelas.

Pertama, ketergantungan kebutuhan ( Wants=, Requires=, BindsTo=dll) yang independen dari dependensi pemesanan ( Before=dan After=). Apa yang Anda lihat di sini adalah siklus ketergantungan pemesanan , yaitu tidak ada hubungannya dengan Wants=dll.

Kedua, ada sejumlah "dependensi default" yang dibuat antara unit tipe tertentu. Mereka dikendalikan oleh DefaultDependencies=arahan di [Unit]bagian (yang diaktifkan secara default ).

Khususnya, kecuali arahan ini secara eksplisit dinonaktifkan, .serviceunit -type apa pun mendapatkan implisit Requires=basic.targetdan After=basic.targetdependensi, yang persis seperti yang Anda lihat. Ini didokumentasikan dalam systemd.service (5) .

intelfx
sumber
Perintah yang Anda kutip bekerja dengan sempurna, dan memang mengungkapkan ketergantungan pada basic.target. Sayang sekali bahwa toolset untuk systemctl sangat kurang, tapi oh well, ini adalah proyek baru
galet
2
@galets: Dilihat dari pengalaman saya, ada beberapa contoh kekurangan seperti itu ... Mungkin suatu hari nanti saya akan berkeliling meningkatkan verbosity dari reporter siklus, menambahkan beberapa informasi yang berguna ke log. Sementara itu, sebenarnya, Anda dapat menggunakan systemd-analyze verify UNITuntuk memeriksa kebenaran unit. Di belakang layar, perintah ini membuat instance virtual systemd dan mencoba memuat UNIT yang diberikan sebagai transaksi awal (seolah-olah memang demikian default.target). Ini tidak akan mengungkapkan informasi baru (dibandingkan dengan log), tetapi setidaknya Anda tidak perlu reboot dengan unit yang diaktifkan untuk melihat apakah itu gagal.
intelfx
systemd request for enhancement (RFE): tingkatkan verbositas reporter siklus
adrelanos
20

Anda bisa memvisualisasikan siklus dengan perintah systemd-analyze verify, systemd-analyze dotdan alat GraphViz dot :

systemd-analyze verify default.target |&
perl -lne 'print $1 if m{Found.*?on\s+([^/]+)}' |
xargs --no-run-if-empty systemd-analyze dot |
dot -Tsvg >cycle.svg

Anda harus melihat sesuatu seperti ini:

masukkan deskripsi gambar di sini

Di sini Anda dapat melihat siklus: c.service->b.service->a.service->c.service

Color legend: 
    black     = Requires
    dark blue = Requisite
    dark grey = Wants
    red       = Conflicts
    green     = After

Tautan:

Evgeny Vereshchagin
sumber
systemd-analyze verifytidak ada di sini pada instalasi debian 8.
sjas
@ Sjas, systemd-analyze verify tersedia sejak v216. coba systemd-verify. Apakah itu ada
Evgeny Vereshchagin
hm, itu tidak ada di Jessie: anonscm.debian.org/cgit/pkg-systemd/systemd.git/tree/debian/…
Evgeny Vereshchagin
1
systemd-analyze verify default.targetsendiri melakukan pekerjaan yang layak dalam menunjukkan loop ...
Gert van den Berg
0

langkah 1: jalankan perintah verifikasi untuk default.target

systemd-analyze verify default.target

langkah 2: amati layanan atau target mana yang disebutkan dalam pesan "systemd Memutus siklus pemesanan dengan menghapus pekerjaan" dan menampilkannya daftar ketergantungan lengkap

systemctl show -p Requires,Wants,Requisite,BindsTo,PartOf,Before,After <service or target name mentioned in the "breaking cycle" message>

langkah 3: lihat grup "setelah" dan "sebelum" di dalam layanan atau file target yang biasanya didefinisikan dalam

/lib/systemd/system

dan menemukan layanan atau target yang dikenal sebagai berurutan tetapi dalam urutan keluar untuk yang satu ini.

contoh:

dbus.service

biasanya memasarkan "setelah"

multi-user.target

tapi "sebelum"

sockets.target

ketergantungan seperti itu dapat dengan mudah diamati dengan menelepon

systemctl list-dependencies default.target

Namun jika file tersebut

/lib/systemd/system/dbus.service

mengandung garis seperti:

Before=multi-user.target

atau

After=sockets.target

atau keduanya secara bersamaan, berarti dbus.service didefinisikan keluar dan itu menyebabkan siklus tak berujung systemd.

yang menyembuhkan sederhana - perubahan kata "Setelah" untuk "Sebelum" dan sebaliknya jika diperlukan.

Oleg Kokorin
sumber