apt-get dist-upgrade
命令,将安装更新到最新的软件包。我使用chroot来完成这个过程,通常的步骤如下:$ 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
[未显示:我还将/mnt/chroot-0/{dev,sys,proc}
作为绑定挂载到真实的/dev
、/sys
和/proc
,因为升级似乎需要这些存在]
然而,在升级到precise之后,这个过程不再起作用 - 最后的umount会失败,因为/mnt/chroot-0
文件系统上仍然有打开的文件。lsof
确认在chroot中有打开文件的进程。这些进程是在dist-upgrade期间启动的,我猜想这是因为chroot中的某些服务需要在包升级后重新启动(例如,通过service postgresql restart
)。
所以,我想我需要告诉upstart停止在这个chroot中运行的所有服务。有可靠的方法吗?
我尝试过:
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
在这个特定的 root 中,initctl list
似乎可以做正确的事情,只列出已经启动的进程。我也尝试了添加这个,正如 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
然而,这些似乎并不能捕捉到所有的情况;已经守护化并重新分配给PID 1的进程不会被停止。我还尝试过:
sudo chroot /mnt/chroot-0 telinit 0
但在这种情况下,init不能区分不同的根目录,并关闭整个机器。
那么,有没有办法告诉init停止特定chroot中的所有进程,以便我可以安全地卸载文件系统?Upstart是否具有在chroot中发送SIGTERM/SIGKILL信号终止所有子进程(就像在正常关机时一样)的功能?