Saya memiliki sejumlah partisi LVM, masing-masing berisi instalasi Ubuntu. Kadang-kadang, saya ingin melakukan apt-get dist-upgrade
, untuk memperbarui instalasi ke paket terbaru. Saya melakukan ini dengan chroot - prosesnya biasanya seperti:
$ sudo mount /dev/local/chroot-0 /mnt/chroot-0
$ sudo chroot /mnt/chroot-0 sh -c 'apt-get update && apt-get dist-upgrade'
$ sudo umount /mnt/chroot-0
[tidak diperlihatkan: Saya juga me-mount dan unmount /mnt/chroot-0/{dev,sys,proc}
sebagai bind-mounts ke yang asli /dev
, /sys
dan /proc
, karena dist-upgrade sepertinya mengharapkan ini ada]
Namun, setelah memutakhirkan ke tepatnya, proses ini tidak lagi berfungsi - umount terakhir akan gagal karena masih ada file yang terbuka di sistem /mnt/chroot-0
file. lsof
menegaskan bahwa ada proses dengan file terbuka di chroot. Proses-proses ini telah dimulai selama dist-upgrade, saya berasumsi ini karena layanan tertentu di chroot perlu direstart (misalnya, melalui service postgresql restart
) setelah paket ditingkatkan.
Jadi, saya pikir saya perlu memberitahu pemula untuk menghentikan semua layanan yang berjalan dalam chroot ini. Apakah ada cara untuk melakukan ini dengan andal?
Saya sudah mencoba:
cat <<EOF | sudo chroot /mnt/chroot-0 /bin/sh
# stop 'initctl' services
initctl list | awk '/start\/running/ {print \$1}' | xargs -n1 -r initctl stop
EOF
Di mana initctl list
tampaknya melakukan hal yang benar dan hanya daftar proses yang telah dimulai di root khusus ini. Saya sudah mencoba menambahkan ini juga, seperti yang disarankan oleh Tuminoid:
cat <<EOF | sudo chroot /mnt/chroot-0 /bin/sh
# stop 'service' services
service --status-all 2>/dev/null |
awk '/^ \[ \+ \]/ { print \$4}' |
while read s; do service \$s stop; done
EOF
Namun, ini tampaknya tidak menangkap segalanya; proses yang telah daemonisasi dan telah diperbaiki ke PID 1 jangan dihentikan. Saya juga sudah mencoba:
sudo chroot /mnt/chroot-0 telinit 0
Tetapi dalam kasus ini, init tidak membedakan antara akar yang terpisah dan mematikan seluruh mesin.
Jadi, apakah ada cara untuk memberitahu init untuk menghentikan semua proses dalam chroot tertentu, sehingga saya dapat dengan aman meng-unmount sistem file? Apakah pemula memiliki fasilitas untuk SIGTERM / SIGKILL semua proses anak (seperti yang akan dilakukan selama shutdown reguler) dalam chroot?
Jawaban:
Saya tidak mempercayai apa pun kecuali kernel untuk menjaga keadaan waras di sini, jadi saya tidak (ab) menggunakan init untuk menyelesaikan pekerjaan ini, saya juga tidak mengandalkan diri saya sendiri untuk mengetahui apa yang sudah atau tidak dipasang (beberapa paket dapat me-mount filesystem tambahan, seperti binfmt_misc). Jadi, untuk proses penyembelihan, saya menggunakan:
Dan untuk umroun chroot, saya menggunakan:
Sebagai tambahan, saya akan menunjukkan bahwa mendekati ini sebagai masalah init mungkin cara yang salah untuk melihatnya, kecuali jika Anda benar-benar memiliki init di chroot dan ruang proses yang terpisah (yaitu: dalam kasus kontainer LXC) . Dengan init tunggal (di luar chroot), dan ruang proses bersama, ini bukan lagi "masalah init", melainkan hanya terserah Anda untuk menemukan proses yang kebetulan memiliki jalur menyinggung, maka proses proc di atas berjalan.
Tidak jelas dari pos awal Anda apakah ini adalah sistem yang sepenuhnya dapat di-boot yang baru saja Anda tingkatkan secara eksternal (seperti yang saya baca), atau apakah itu chroot yang Anda gunakan untuk hal-hal seperti pembuatan paket. Jika yang terakhir, Anda mungkin juga menginginkan kebijakan-rc.d di tempat (seperti yang dijatuhkan oleh mk-sbuild) yang hanya melarang pekerjaan init dimulai di tempat pertama. Jelas, itu bukan solusi yang masuk akal jika ini dimaksudkan untuk menjadi sistem yang dapat di-boot juga.
sumber
policy-rc.d
terlihat seperti pendekatan yang menarik (saya bisa menghapusnya setelah berinteraksi dengan chroot). Apakah ini mempengaruhi pekerjaan/etc/rc*.d
- dan-/etc/init/*.conf
gaya?Anda telah mengidentifikasi sendiri masalahnya: Beberapa hal berjalan
service ...
selama dist-upgrade danservice
bukan bagian dari pemula, tetapi bagian darisysvinit
. Tambahkan sihir awk serupa di sekitarservice --status-all
untuk menghentikan layanan sysvinit seperti yang Anda gunakan untuk layanan pemula.sumber
sudo chroot /mnt/chroot-0 service --list-all
dansudo chroot /mnt/chroot-0 initctl list
, yang keduanya melaporkan tidak ada layanan yang berjalan. Namun,/usr/bin/epmd
(dari erlang-base) masih berjalan.Saya tahu pertanyaan ini cukup lama, tetapi saya pikir itu relevan hari ini seperti pada tahun 2012, dan semoga seseorang menemukan kode ini berguna. Saya menulis kode untuk sesuatu yang saya lakukan, tetapi saya pikir saya akan membagikannya.
Kode saya berbeda, tetapi idenya sangat mirip dengan @ infinity (pada kenyataannya - satu-satunya alasan saya sekarang tahu tentang / proc / * / root adalah karena jawabannya - terima kasih @ infinity!). Saya juga menambahkan beberapa fungsi tambahan keren
Sekarang Anda akan melakukan 2 hal untuk memastikan chroot dapat dilepas:
Bunuh semua proses yang mungkin berjalan di chroot:
Bunuh semua proses yang mungkin berjalan di luar chroot, tetapi mengganggu itu (mis: jika chroot Anda adalah / mnt / chroot dan dd menulis ke / mnt / chroot / testfile, / mnt / chroot akan gagal di-unmount)
Catatan: Jalankan semua kode sebagai root
Selain itu, untuk versi yang tidak terlalu rumit, ganti KILL_PID dengan keduanya
kill -SIGTERM
ataukill -SIGKILL
sumber
jchroot : chroot dengan lebih banyak isolasi.
Setelah perintah Anda dieksekusi, proses apa pun yang dimulai dengan eksekusi perintah ini akan dimatikan, IPC apa pun akan dibebaskan, setiap titik pemasangan akan dilepas. Semua bersih!
schroot belum dapat melakukan ini, tetapi ini sudah direncanakan
Saya telah mengujinya dengan sukses di OpenVZ VPS, yang tidak dapat menggunakan buruh pelabuhan atau lxc.
Silakan baca blog penulis untuk detailnya:
https://vincent.bernat.im/en/blog/2011-jchroot-isolation.html
sumber
schroot: Ini memiliki fitur manajemen sesi. Ketika Anda menghentikan sesi semua prosesnya terbunuh.
https://github.com/dnschneid/crouton/blob/master/host-bin/unmount-chroot : Skrip ini membunuh semua proses chroot dan melepas semua perangkat yang terpasang.
sumber