我正在编写一个 bash 脚本来将我的 rootfs 更改为 SD 卡上的另一个 rootfs。
步骤大致为:
mount /dev/hda1 /new-root
cd /new-root
pivot_root . old-root
exec chroot . sh <dev/console >dev/console 2>&1
umount /old-root
这在交互模式下按预期工作,但在脚本中不工作,因为解释器在 中运行old-root
,我无法卸载它。
因此,我尝试使用中间脚本,在其中我像这样杀死父级:
# parent
exec chroot sd_card_fs sh -c script.sh
# son
cat script.sh
...
kill -9 $PPID
umount /old-root
...
这不起作用,因为儿子自杀,杀死了其父母,我发现这个解决方案有点肮脏。
所以我的问题是:
- 有没有比调用另一个脚本来完成这项工作更干净的方法?如果没有,我该如何修复它?
我真的想尽可能地减少人机交互,因此调用一个脚本,等待它完成启动另一个脚本是不行的,除非没有其他解决方案。
答案1
但是“父”脚本中的最后一个命令取代它与“儿子”。就是这样exec
。您不应该有任何可以杀死的父进程。
此类脚本可以仅有的当脚本的 PID 为 1 时工作,因此没有其他进程[*]。 您必须已启动init=/bin/bash
。 请记住使用以下方式调用您的脚本exec
,因此它取代了 PID 1。
不要使用延迟卸载,这意味着您不会看到错误消息。
我 99% 确信您的惰性卸载尚未完成。我不确定如何测试这一点,除非您使用 ext4 或 ext3,否则file -s /dev/$ROOT_DEV
应该显示“需要日志恢复”(即尚未完全卸载)。
kill
如果您删除并按照上面的粗体说明进行操作,我希望您的第一次尝试能够成功。不过我可能错过了一些东西。
[*] 或者,在将其执行的路径安排在目标文件系统上之后,您需要告诉 init 重新执行自身。但这对我来说听起来是一个糟糕的主意。让事情变得简单。