推荐一个前几天看到的神奇的项目,takeover.sh,中文可以译为接管
引言
如果想要重装系统或者执行一些硬盘扫描修复之类的操作,一般都要进入到另一个维护环境内进行。
- 如果是本地机器,可以用优盘安装PE系统
- 如果是vps,可以使用救援系统
- 如果是杜甫,可以用IPMI
总之,你没法直接格式化一个正在运行的系统,因为硬盘被各种进程占用并处于忙碌状态。
于是,曾经琢磨过一个问题,有没有可能在系统不重启的前提下,使系统进入一种临时的维护状态,比如在内存加载一个临时系统,并将目前的运行环境切换过去,由新的临时系统来接管当前的系统资源。
如果你想到了这个问题,那么takeover.sh便是这个问题的解答!
看一下takeover.sh的英文介绍:
A script to completely take over a running Linux system remotely, allowing you to log into an in-memory rescue environment, unmount the original root filesystem, and do anything you want, all without rebooting. Replace one distro with another without touching a physical console.
一个脚本,用于完全远程接管正在运行的 Linux 系统,允许您登录内存救援环境,卸载原始根文件系统,并执行任何您想要的操作,所有这些都无需重新启动。 将一个发行版替换为另一个发行版,而无需接触物理控制台。
天呐,这是什么魔法,看了下代码,没有几行,但是很灵活的运用了telinit/chroot/pivot_root/tmpfs等技巧。
怎么使用
那么问题来了,怎么用呢。想要进入这个临时的接管系统中,大概可以分为以下几个步骤:
挂载临时系统
mkdir /takeover
mount -t tmpfs tmpfs /takeover -o size=150M # 你需要的内存盘大小
temp_os_url='https://github.com/LloydAsp/templates/releases/download/v1.0.0/alpine-takeover.tar.gz'
curl -sL $temp_os_url | tar -C /takeover -xz
mv /takeover/takeover/* /takeover
这里我们使用了一个alpine系统作为临时系统,你可以使用任何你想要的系统,比如用debootstrap塞一个debian或者ubuntu进去,只要有对应的文件即可。
准备一些工具并编译fakeinit
apt update; apt-get install -y busybox git build-essential
wget -O /takeover/busybox https://www.busybox.net/downloads/binaries/1.26.2-defconfig-multiarch/busybox-x86_64
chmod a x /takeover/busybox
git clone https://github.com/marcan/takeover.sh /tmp/takeover.sh/
cp -a /tmp/takeover.sh/* /takeover/
cd /takeover
gcc -static fakeinit.c -o fakeinit
cp usr/bin/passwd bin/
这里编译的fakeinit将用于替换你的默认启动进程(init/systemd)
开始接管
sh takeover.sh
每当takeover询问你是否OK的时候,就输入OK,回车
通过ssh进入到新的临时系统内
新开一个终端,连接到你的ip地址,端口为80,注意不是原来的22端口
ssh -p80 root@your_host
好了,你已就位,随心所欲的折腾
现在你已经进入了临时系统内,你可以为所欲为了,比如格式化任何硬盘,关闭任何(除了fakeinit下属进程外的)任何进程。当然,你也可以在这个环境下手动安装系统,一般的步骤是格式化硬盘,灌入文件、加载内核、修复引导等等。
来看下这个进程图
这里是临时系统内部的进程图,可以看到,根进程已经被替换为fakeinit,新系统的sshd在最下面。原系统内的各种进程仍然在运行,你可以通过按k键,然后选择SIGKILL杀死这些进程,放心这不会使你的临时系统崩溃。

退出
可以使用reboot -f或者echo b > /proc/sysrq-trigger退出
畅想
目前的kvm dd脚本,基本都是重启后进行安装步骤。takeover.sh可以提供一种新的可能,直接在未重启系统的情况下进行安装。我进行了相关的尝试,并证明这个思路完全可行,后面有时间会给出一些实验性的支持脚本。

好像能用来DD备份
@Not-Oles #36
我成功尝试的环境:原系统debian 11、中间临时系统alpine、使用debootstrap创建新系统或者直接用rootfs覆盖原系统文件。
经历过因为忘记mount临时系统所在目录为tmpfs导致失败的情况,以及忘记更新引导区导致无法重启的情况
The environment I successfully tried: the original system is debian 11, the intermediate temporary system is alpine, using debootstrap to build the new system or directly overwriting the original system files with rootfs.
I have experienced failures due to forgetting to mount directory for temp os as tmpfs, and failure to restart due to forgetting to update the boot sector。
@Not-Oles #36
忘了说了,umount旧的文件分区,需要在临时系统上关闭原系统残存的进程,因为可能仍旧在占用设备
Forgot to mention, to umount the old file partition, you need to close the remaining processes of the original system on the temporary system, because the device may still be occupied.