Bagaimana saya bisa menginstal paket tanpa memulai layanan terkait mereka?

13

Seperti yang mungkin Anda ketahui, secara default ketika Anda menginstal paket pada sistem berbasis Debian atau Ubuntu, jika paket tersebut berisi layanan, layanan itu umumnya akan diaktifkan dan mulai secara otomatis ketika Anda menginstal paket.

Ini masalah bagi saya.

Saya menemukan diri saya perlu mengelola template untuk membuat kontainer LXC. Ada beberapa wadah, masing-masing sesuai dengan rilis Debian atau Ubuntu. (Ada juga wadah berbasis Red Hat, tetapi mereka tidak relevan di sini.)

/var/lib/libvirt/filesystems/debian6_template
/var/lib/libvirt/filesystems/debian7_template
/var/lib/libvirt/filesystems/ubuntu1004_template
/var/lib/libvirt/filesystems/ubuntu1204_template

Kadang-kadang saya akan menemukan bahwa template memiliki paket yang hilang atau memerlukan beberapa perubahan lainnya, jadi saya akan chroot ke dalamnya untuk menginstal paket. Sayangnya ketika saya melakukan itu, saya berakhir dengan beberapa salinan dari layanan paket berjalan!

Sebagai contoh, saya menemukan template tidak memiliki daemon syslog, jadi saya menginstalnya:

for template in /var/lib/libvirt/filesystems/{debian,ubuntu}*_template; do
    chroot $template apt-get install rsyslog
done

Dan segera berakhir dengan empat salinan rsyslog berjalan. Belum lagi dua salinan exim4. Ups!


Saya membaca di suatu tempat (meskipun saya tidak dapat menemukannya lagi sekarang) bahwa itu seharusnya tidak memulai layanan ketika berjalan di chroot, tetapi itu jelas tidak terjadi di sini.

Satu panggilan hack jahat yang berpotensi untuk mengganti sementara berbagai perintah yang benar-benar memulai layanan, seperti start-stop-daemondan initctl, meskipun ini jauh lebih banyak pekerjaan daripada yang saya ingin lakukan. Jika saya tidak punya pilihan lain, ...

Solusi ideal di sini adalah sistem berbasis Debian untuk berhenti melakukan omong kosong ini, tetapi gagal itu, mungkin opsi baris perintah yang tidak jelas atau tidak terdokumentasi untuk apt-get?

Jika tidak jelas, saya benar-benar ingin menyimpan apa pun yang terkait dengan mengelola template di luar template, jika memungkinkan.

Michael Hampton
sumber

Jawaban:

23

Untuk debian Anda dapat melakukan ini dengan policy-rc.d . Inilah satu penjelasan :

Skrip pengelola paket seharusnya hanya berinteraksi dengan sistem init melalui invoke-rc.d, update-rc.d dan header skrip init LSB ... invoke-rc.d akan, sebelum melakukan aksinya, periksa apakah /usr/sbin/policy-rc.d dapat dieksekusi, akan memanggilnya dengan nama layanan masing-masing dan nomor runlevel saat ini pada baris perintah dan bertindak sesuai dengan kode keluarnya. Misalnya, nilai pengembalian 101 akan mencegah tindakan yang direncanakan diambil. Ini termasuk dimulainya layanan secara otomatis pada saat instalasi paket serta penghentian layanan pada penghapusan paket dan mengurangi ritual stop-upgrade-restart selama peningkatan paket untuk hanya melakukan upgrade yang mungkin membuat versi lama dari layanan berjalan

Karena Anda tidak ingin layanan apa pun mulai, skrip kebijakan-rc.d Anda bisa sederhana

#!/bin/sh
exit 101

Ini adalah teknik yang digunakan oleh alat-alat seperti pbuilder dan mkimage-debootstrap Docker .

Sayangnya, teknik ini tidak berfungsi dengan chroots Ubuntu . Paket yang terintegrasi dengan panggilan sistem init pemula / usr / sbin / initctl alih-alih memanggil-rc.d selama instalasi, dan initctl tidak berkonsultasi dengan kebijakan-rc.d. Menurut penulis pemula ini solusinya adalah mengganti / sbin / initctl dengan symlink ke / bin / true dalam chroot. Anda dapat melihat ini di mkimage-debootstrap juga, mereka tahu

dpkg-divert --local --rename --add /sbin/initctl
ln -sf /bin/true sbin/initctl
sciurus
sumber
Ini tampaknya cukup bersih, meskipun juga harus dihapus sebelum membuat wadah dari template.
Michael Hampton
1
Terima kasih untuk ini. Saya mungkin berakhir hanya harus merobek skrip mkimage-debootstrap Docker, karena mereka tampaknya sebagian besar memecahkan masalah ini.
Michael Hampton
4

Anda dapat melakukan:

export RUNLEVEL=1
for template in /var/lib/libvirt/filesystems/{debian,ubuntu}*_template; do
    chroot $template apt-get install rsyslog
done
exit

Saya belum mengujinya dengan chroot, tetapi harus berhasil. Pada awalnya ia menetapkan variabel lingkungan RUNLEVEL, sehingga proses yang diprakarsai oleh apt-get tidak akan memulai layanan apa pun, karena mereka akan "berpikir" sistem berjalan dalam mode tunggal. Karena lingkungan dimodifikasi dengan cara yang dapat memengaruhi perintah di masa mendatang, maka diperlukan untuk keluar dari shell ketika lingkungan yang diubah tidak lagi diperlukan, ini dilakukan dengan keluar dari perintah di akhir. Ada mungkin beberapa paket (jarang?) Yang tidak akan menginstal dengan benar dalam mode tunggal (tapi AFAIK ini seharusnya tidak menjadi masalah dalam banyak kasus).

DavisNT
sumber
Apakah export RUNLEVEL=1bagian penting di sini? Apa sebenarnya penyebabnya terjadi?
Michael Hampton
@MichaelHampton Saya percaya variabel lingkungan RUNLEVEL akan memberikan level run saat ini. Dalam hal ini dia hanya menimpanya sehingga aplikasi apa pun akan berpikir itu berjalan pada 1. Ini semacam "kludge" tetapi sudah cukup.
WinkyWolly
Menambahkan penjelasan pada jawaban asli. Pada dasarnya inilah yang dikatakan @WinkyWolly.
DavisNT
Sayangnya rsyslogkebetulan ada salah satu paket "langka" yang meledak sepenuhnya ketika mencoba menginstal cara ini. Ini mungkin masih berguna, jadi Anda dapat tetap mengikuti :)
Michael Hampton