BusyBox 提供 switch_root 專門解決 initramfs (rootfs) 無法 pivot_root/umount 的問題,一次完成:移動掛載點、清理 rootfs、切換根目錄、執行新 init。
switch_root [-c /dev/console] NEW_ROOT NEW_INIT [ARGS...]
NEW_ROOT:真實根檔案系統掛載點 (如 /mnt、/sysroot),執行前必須已掛載。NEW_INIT:真實系統 init 路徑 (通常 /sbin/init)。-c /dev/console:可選,重導向主控台裝置 (通常不需指定)。ARGS:傳遞給新 init 的參數。switch_root: not rootfs)/init (PID 1) 中直接呼叫,不能由子進程/腳本調用。exec 執行:exec switch_root ... 替換當前進程映像,保持 PID 1 不變。若用 switch_root ... (無 exec) 則 fork 子進程,PID 變更導致失敗。
#!/bin/sh
# 掛載必要虛擬檔案系統
[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
# 掛載 sysfs/proc
mount -t sysfs -o nodev,noexec,nosuid none /sys
mount -t proc -o nodev,noexec,nosuid none /proc
# 裝置節點管理:優先 devtmpfs,失敗回退 tmpfs + 手動建立基礎節點
if ! mount -t devtmpfs -o mode=0755 none /dev; then
mount -t tmpfs -o mode=0755 none /dev
mknod /dev/null c 1 3
mknod /dev/ptmx c 5 2
mknod /dev/console c 5 1
mknod /dev/kmsg c 1 11
fi
mkdir /dev/pts
mount -t devpts -o noexec,nosuid,gid=5,mode=0620 none /dev/pts || true
# mdev/udev 掃描硬體建立完整裝置節點
mdev -s
# 掛載真實根分區 (實際部署應從 /proc/cmdline 解析 root= 參數)
mount /dev/sda3 /root
# 切換根檔案系統 (鐵律:exec + PID 1)
echo "switch_root /root /sbin/init"
exec switch_root /root /sbin/init
gid=5 通常對應 tty 群組。/sys 針對非 devtmpfs 管理的裝置建立節點 (如舊驅動、虛擬裝置)。/proc/cmdline 中 root=UUID=... 或 root=/dev/...,而非硬編碼。rd.break (dracut) 或 init=/bin/sh 進入 initramfs Shell 除錯。ls -la /dev 確認裝置節點;cat /proc/cmdline 檢查參數;mount 檢查掛載狀態。switch_root 失敗,檢查:是否 PID 1、是否 exec、NEW_ROOT 是否掛載、NEW_INIT 是否存在且可執行。