zoukankan      html  css  js  c++  java
  • 将pebuilder变成dibuilder.sh,将di tools集入boot层(1):mini debian iso的产生

    本文关键字:mini debian,minimal-debian,debootstrap linux通用版,将di and di tools集入boot层

    在《利用增强tinycorelinux remaster tool打造你的硬盘镜像及一种让tinycorelinux变成Debian install体的设想》中我们比较了tc remaster tool与debian netinstall live cd的关系,但其实debian install系列中(livecd相当于debootstrap的ncurse界面版,也有gtk界面的)起主要作用的是其/bin中的debconf等di工具,今天要谈到的debootstrap相当于a console remaster tool。里面也有debconf。

    在镜像http://xxx url/debian/dists/jessie/main/installer-amd64/current/images/netboot/debian-installer/amd64路径下,那个initrd实际是支持di运行的最小live系统,这里还有一个29m的ncurses mini.iso在mirror/debian/dists/jessie/main/installer-amd64/current/images/netboot/mini.iso,还有一个49mb的gtk install mini.iso

    本文尝试探索debian下用来remaster的机制deboostrape(debootstrap有一个特点:只支持debian系因为它要引用host上的debconf,否则提示Couldn't work out current architecture),实现将pebuilder.sh变成dibuilder.sh(即用peubilder代替debootstrap实现在其它linux上也能remastering debian,它们原理类似),最终实现tc转debian,为什么由tc转到debian?在《利用增强tinycorelinux remaster.....变成Debian install体的设想》文尾也说了,debian has many quality packages available for easy integration,而且它支持arm64,更何况它还有上述的netinstall iso和debconf/debootstrap。

    debian和ubuntu都是社区发行的,跟redhat/centos这样的有公司支持的不一样,严格来说ubuntu也有公司支持,但是跟后者还有是区别,redhat中是可以包含商业驱动(firmware)发布的,而debian中不能,除了维护周期不一(redhat往往10年一周期,而deb的往往一年到3年),除此之外,它们的质量其实是相近的。

    debootstrap是创建你自己的debain发行版的工具基础,它是一套脚本,但它会调用 glibc 的一下工具。  在一个debian发行版上,sudo apt-get download debootstrap,然后sudo dpkg -x debootstrapxxx.deb .(注意这个.代表的当前目录)可看到脚本,主体是usr/sbin/debootstrap,usr/share/debootstrap/functions和usr/share/debootstrap/scripts下的脚本。

    debootstrap初步尝试minirootfs_test

    原理上,debootstrap主程序主要是调用处理,functions负责所有的细节事务,然后scripts/debian-common才是主流程(download_indices,work_out_debs,first_stage,second_stage->core packages、required packages、base packages,可见sec stage才是主要实现下载debs的部分,这是debootstrap主要的工作和全部的工作:分析镜像,下包,其它不干)。

    debconf会视设置决定弹不弹窗口,这也是集成到netinstall livecd (mini.iso)和preseed中的东西,它被允许弹出界面。在/scripts/debian-common中我们发现:

    	DEBIAN_FRONTEND=noninteractive
    	DEBCONF_NONINTERACTIVE_SEEN=true
    	export DEBIAN_FRONTEND DEBCONF_NONINTERACTIVE_SEEN
    

    我们看下它的初步使用,在使用上,它的调用形式为:

    如:sudo debootstrap --verbose --no-check-gpg --no-check-certificate [--print-debs] --variant=minbase jessie minirootfs_test http://mirrors.aliyun.com/debian/
    (命令中的options顺序也很重要,在 --variant=后就不要放其它参数了,否则你自己也会混乱,把所有的其它参数都放它前面,jessie minirootfs即为suite,target往往固定出现,放--no-check-gpg --no-check-certificate是因为本地mirror可以避免认证过程,mirror支持/target file:///cdrom/(这也就是net install cd的做法,那个官网下到的300多m的并非pebuilder.sh中用到的initrd对应的那个20多m的mini.iso,预设的variants=minbase就是基本最小的可定义配置了)

    minbase是最小的配置,我们看下minbase从何而来,在/scripts/debian-common和debootstrap/debian-common中:

    	elif doing_variant minbase; then
    		base="apt" 只安装必要的包(required)和apt,(实际上好多debian精简系统中只要求一个最小debain dpkg -i就可以完成安装deb了,不需要apt)
    	fi
    

    上述命令若指定了[--print-debs]会在打印要安装的包后退出,这个选项会输出minbase调试如下:

    I: Found additional required dependencies: acl adduser dmsetup insserv libaudit-common libaudit1 libbz2-1.0 libcap2 libcap2-bin libcryptsetup4 libdb5.3 libdebconfclient0 libdevmapper1.02.1 libgcrypt20 libgpg-error0 libkmod2 libncursesw5 libprocps3 libsemanage-common libsemanage1 libslang2 libsystemd0 libudev1 libustr-1.0-1 procps systemd systemd-sysv udev
    
    I: Found additional base dependencies: debian-archive-keyring gnupg gpgv libapt-pkg4.12 libreadline6 libstdc++6 libusb-0.1-4 readline-common 
    acl adduser base-files base-passwd bash bsdutils coreutils dash debconf debconf-i18n debianutils diffutils dmsetup dpkg e2fslibs e2fsprogs findutils gcc-4.8-base gcc-4.9-base grep gzip hostname init initscripts insserv libacl1 libattr1 libaudit-common libaudit1 libblkid1 libbz2-1.0 libc-bin libc6 libcap2 libcap2-bin libcomerr2 libcryptsetup4 libdb5.3 libdebconfclient0 libdevmapper1.02.1 libgcc1 libgcrypt20 libgpg-error0 libkmod2 liblocale-gettext-perl liblzma5 libmount1 libncurses5 libncursesw5 libpam-modules libpam-modules-bin libpam-runtime libpam0g libpcre3 libprocps3 libselinux1 libsemanage-common libsemanage1 libsepol1 libslang2 libsmartcols1 libss2 libsystemd0 libtext-charwidth-perl libtext-iconv-perl libtext-wrapi18n-perl libtinfo5 libudev1 libustr-1.0-1 libuuid1 login lsb-base mawk mount multiarch-support ncurses-base ncurses-bin passwd perl-base procps sed sensible-utils startpar systemd systemd-sysv sysv-rc sysvinit-utils tar tzdata udev util-linux zlib1g apt debian-archive-keyring gnupg gpgv libapt-pkg4.12 libreadline6 libstdc++6 libusb-0.1-4 readline-common
    

    (再看大小cd minirootfs_test;sudo du -hs * .里面占用最大的usr,var,lib),整个文件夹有202mb,返回上层打包整个minirootfs_test发现有100m,毕竟它虽然不干什么事,但包括systemd。)在/var/cache/apt中也有缓存包大约67m

    我们要做的工作就是把它变小。变成仅支持apt的最小debain发行版。最好10-30m之间。类mini.iso,(那么,为什么不直接用debain mirror提供的那个29m的mini iso呢,因为它是for install的。里面没有apt,不能当正常的linux用),除了上面的初步判断apt cache可删,整个rootfs中的机制,如systemd依赖的东西也会导致占用过大,要删,更要以一种clean的方式去删,所以不建议直接删cache而要进入chroot。

    以下这是一些工程和文章(当然它们都是debootstrap的应用),debootstrap 主页上也有更多关于构建更小的或更适合的容器的信息:

    https://www.cnblogs.com/fengyc/p/6114648.html《基于 debootstrap 和 busybox 构建 mini ubuntu》
    http://github.com/bitnami/minideb 这个包有20多m符合我们的要求,但是它是容器用的,跟我们需求,要在云主机和PC上用不一样。
    刚好还看到一个用debian组装类我的minstackos的一个东东https://github.com/zhangguangyan/debian-mini-desktop,也集成了vs,docker,chrome它用了openbox桌面而不是仅止于用xorg+kisos mode chrome,它是用packer 调用preseed应答自动完成的。minideb也是调用preseed不过它是脚本调用没有借助packer,https://blog.csdn.net/mountzf/article/details/51707853 《定制适用于ARM平台的Ubuntu rootfs(根文件系统)》http://linux-sunxi.org/Debootstrap

    下面开始实践

    使用debootstrap和chroot创建tinydebianlive

    我们是在一台debian8.11(jessie)上尝试的(专门选择host与target同版同架构),20201231现在的版本是currently version 10.7.0)。从这里http://cdimage.debian.org/cdimage/archive/寻找debian-8.11.0-amd64-netinst.iso安装到虚拟机上主机名设为tinydebian跳过root用户(不跳过稍后你普通用户无法sudo,新用户之前完成的步骤,它们把这个叫做basesystem,好多系统发行用的都是di的界面和liveinstall,集成东西到cdrom as deb source这样来的)新建普通用户名密码td(short for tinydebian)仅安装openssh和standsystemutils,进去sudo apt-get install debootstrape安装debootstrap(apt list --installed,debootstrap/oldoldstable,now 1.0.67+deb8u1 all [installed]),https://cdimage.debian.org/debian-cd/current/amd64/list-cd/可以看到打包的deb列表,我们看到它对source也进行打包(deb发行的文件组织分类虽然很科学很细,但是很不友好的,因为我们需要flat和plain的结构,tc mirror那套就很好)

    ssh登录这个主机,看ip需执行ifconfig,如果发现不了就sudo ifconfig,否则apt-get install net-tools再sudo ifconfig,然后:

    sudo debootstrap --variant=minbase --include=module-init-tools,sudo,ifupdown,isc-dhcp-client jessie tinydebianlive http://mirrors.aliyun.com/debian/

    准备chroot尝试(接下来是一个跟cross compile gcc的lfs之类的大课题了,当然, 有现成包定制一下rootfs这比lfs不知道要简单多少倍),网上说从主机到chroot环境中要经过mount proc等,,但是我试了下也可以直接sudo chroot tinydebianlive /bin/bash,猜想这个debootstrap stage1就作了自动处理,所以不自己手动作处理,还有先做一些准备工作消除chrome环境中apt-get install的warning,不作也没关系,--include是往base里除默认的apt外再加入的一些东西,加在这里跟接下来加在sudo chroot tinydebianlive apt-get -yqq --force-yes --no-install-recommends install xxx里的区别是加这里镜像会更小,而且它们是必要的,module-init-tools因为它提供depmod,ifupdown,isc-dhcp-client是为了使基本网络逻辑dhcp生效,sudo是没法这个太基础了,关于要安装哪些包接下来还会说到,最后,由于下面的命令全部计划在ssh界面上粘贴,,接下来的脚本不推荐用root运行,所以只能用这种方法以避免混入主机上的权限给镜像带来污染,继续:

    1)首先是驱动和内核模块,minbase 中没有这些,需要从 kernel 或本机中把模块 copy 进去,当然还是下载集成省事。

    (你也可以直接从http://chuangtzu.ftp.acc.umu.se/cdimage/unofficial/non-free/firmware/jessie/current/firmware.cpio.gz下载解压得到或者从http://mirrors.163.com/debian/dists/jessie/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz这样的地方提取更小的组合):

    为保险起见sudo echo回车一下,省得接下来命令中有sudo因为交互输入密码被截断,

    sudo echo
    

    然后,用微缩版的hdmedia initrd+cd mini.iso firmware,后者有virtio:

    (sudo du -hs tinydebianlive/*,整包201M)
    
    echo 'td' | sudo mkdir hdmedia-extracted netboot-extracted
    
    echo 'td' | sudo sh -c 'wget -qO- http://mirrors.aliyun.com/debian/dists/jessie/main/installer-amd64/current/images/hd-media/initrd.gz > hdmedia-extracted/initrd.gz'
    cd hdmedia-extracted
    echo 'td' | sudo sh -c 'gunzip -cq initrd.gz | cpio -idmv'
    echo 'td' | sudo cp -af lib/modules ../tinydebianlive/lib
    
    echo 'td' | sudo sh -c 'wget -qO- http://mirrors.aliyun.com/debian/dists/jessie/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz > netboot-extracted/initrd.gz'
    cd netboot-extracted
    echo 'td' | sudo sh -c 'gunzip -cq initrd.gz | cpio -idmv'
    echo 'td' | sudo cp -rf lib/modules/3.16.0-6-amd64/kernel/drivers/virtio/ ../tinydebianlive/lib/modules/3.16.0-6-amd64/kernel/drivers/
    echo 'td' | sudo cp -f lib/modules/3-16.0-6-amd64/kernel/drivers/block/virtio_blk.ko ../tinydebianlive/lib/modules/3-16.0-6-amd64/kernel/drives/block/
    echo 'td' | sudo cp -f lib/modules/3.16.0-6-amd64/kernel/drivers/net/virtio_net.ko ../tinydebianlive/lib/modules/3.16.0-6-amd64/kernel/drivers/net/
    
    cd ..
    echo 'td' | sudo chroot tinydebianlive depmod
    sudo sh -c "echo 'virtio_ring' >> tinydebianlive/etc/modules-load.d/modules.conf"
    sudo sh -c "echo 'virtio_balloon' >> tinydebianlive/etc/modules-load.d/modules.conf"
    sudo sh -c "echo 'virtio' >> tinydebianlive/etc/modules-load.d/modules.conf"
    sudo sh -c "echo 'virtio_pci' >> tinydebianlive/etc/modules-load.d/modules.conf"
    sudo sh -c "echo 'virtio_blk' >> tinydebianlive/etc/modules-load.d/modules.conf"
    sudo sh -c "echo 'virtio_net' >> tinydebianlive/etc/modules-load.d/modules.conf"
    (这个步骤给sudo du -hs tinydebianlive/lib/modules/$(uname -r)/kernel/*,总共增加约10几M)
    

    在选择modules是用http://mirrors.aliyun.com/debian/dists/jessie/main/installer-amd64/current/images/hd-media/还是用http://mirrors.aliyun.com/debian/dists/jessie/main/installer-amd64/current/images/netboot/debian-installer/amd64/中的initrd时,其实用hd-media的要好些,第一它小8m第二它完善些,net-boot应该不只是有virtioblk还有全套pxe的驱动16m,而hd-media的仅仅是没有virtioblk而已。前者的缺陷还在于,1)安装完之后,scsi的支持需要/etc/modules-load.d/modules.conf中填入 scsi_mod和sd_mod二行,否则cat /proc/devices的blocks中无法显示(内核无法注册设备需要进去后手动modprobe),而后者只需要从前者提取一个virtio_blk.ko扔进lib/modules/3-16.0-amd64/kernel/drives/block/再在/etc/modules-load.d/modules.conf以boot-time加载就行了,事实上,云主机只是hd-media加virtio的一个特例,---- 即使这样之后,前者也不能在/dev/block,/dev/disk/by-xxx中发现有任何东西,也就发现不了任何盘(加载驱动后cat /proc/devices内核中注册了那些设备,但并没有生成设备文件),这不是udev的作用,而仅是modules的作用,后者一切完美,前者的缺陷还在于,2)安装完之后,启动时因缺少驱动在控制台需要手动return一下才能显login提示,而后者一切完美,3)无论是hd-media还是netbook,都不用cp udev rules from /lib/udev/rules.d/*storage.rules到/etc/udev/rules.d,这仅仅是modules本身的作用。别去相信udevadm control --reload-rules && udevadm trigger之类的动态udev调试 4)貌似缺少modules也会导致启动后计算random熵hang住?

    你也可以用完整版的firmware代替上面二个组合:

    (sudo du -hs tinydebianlive,201M)
    echo 'td' | sudo apt-get download linux-image-$(uname -r)
    echo 'td' | sudo dpkg -x $(sudo find . -type f -name "linux-image-$(uname -r).deb" | head -n 1) linux-image-$(uname -r)
    echo 'td' | sudo cp -af linux-image-$(uname -r)/lib tinydebianlive/
    echo 'td' | sudo chroot tinydebianlive depmod
    (sudo du -hs tinydebianlive/lib/modules/$(uname -r)/kernel/
    ,这个步骤给201M新增了167M)

    (ps:这步其实完全可以省掉,如果你的平台没有装额外modules的需求,或者必要的modules和驱动已作为in built module做到了内核中也不需要这步)

    2)然后是init脚本:

    cat << EOF | sudo tee tinydebianlive/init
    #!/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
    mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
    mount -t proc -o nodev,noexec,nosuid proc /proc
    # Some things don't work properly without /etc/mtab.
    ln -sf /proc/mounts /etc/mtab
    
    grep -q '<quiet>' /proc/cmdline || echo "Loading, please wait..."
    
    # Note that this only becomes /dev on the real filesystem if udev's scripts
    # are used; which they will be, but it's worth pointing out
    if ! mount -t devtmpfs -o mode=0755 udev /dev; then
            echo "W: devtmpfs not available, falling back to tmpfs for /dev"
            mount -t tmpfs -o mode=0755 udev /dev
            [ -e /dev/console ] || mknod -m 0600 /dev/console c 5 1
            [ -e /dev/null ] || mknod /dev/null c 1 3
    fi
    mkdir /dev/pts
    mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true
    mount -t tmpfs -o "noexec,nosuid,size=10%,mode=0755" tmpfs /run
    mkdir /run/initramfs
    # compatibility symlink for the pre-oneiric locations
    ln -s /run/initramfs /dev/.initramfs
    
    # Set modprobe env
    export MODPROBE_OPTIONS="-qb"
    
    # mdadm needs hostname to be set. This has to be done before the udev rules are called!
    if [ -f "/etc/hostname" ]; then
            /bin/hostname -b -F /etc/hostname 2>&1 1>/dev/null
    fi
    
    exec /sbin/init
    EOF
    
    sudo chmod +x tinydebianlive/init
    
    for i in $(find tinydebianlive/etc/systemd/system/getty.target.wants -type f); do
        sudo sed -e "s|/sbin/agetty --noclear %I $TERM|/sbin/agetty --noclear %I $TERM -a td|" -i $i
    done
    

    (从第2步过后的镜像经过打包之后都能进入shell,但缺乏用户和网络等支持,见稍后的打包测试方法)

    1. 修正用户机制和网络

    以下好多内容都可以can be done from both inside and outside of the chroot.先ping www.baidu.com 看下是否有网络,没有网络需要退出文件系统,把宿主机的reslov.conf文件拷贝到相应位置即可。

    这里的问题是需要装一些packages,会增大最终镜像体积(所以保持最小原则的情况下能加的都加到了debootstrap命令中),为了使最终系统更加可用,你可能需要安装language-pack-en-base,net-tools iputils-ping wget openssh-server等基本工具,在安装包的过程中会有一些错误,都是因为chroot环境缺少正常环境的一些环变和小工具导致的,不过没关系。
    由于vi ping这些简单工具主机上就有,而且依赖没有问题,直接从宿主复制就行,通过apt-get install安装没必要。但sudo,openssh-server这俩不一样这俩涉及到复杂配置(deb包如果有服务加入sysv或systemd,它会在包配置阶段完成,,deb包安装完有一个设置过程,其实tce.installed中也可以放脚本设置。但安装包还是静态的好,解压和设置离线的好)

    sudo cp -f /etc/resolv.conf tinydebianlive/etc/resolv.conf
    sudo cp -f /etc/hostname tinydebianlive/etc/hostname
    sudo cp -f /etc/hosts tinydebianlive/etc/hosts
    sudo sh -c "echo '
    ' >> tinydebianlive/etc/issue"
    sudo sh -c "echo 'user td's passwd is td' >> tinydebianlive/etc/issue"
    
    sudo cp -f /etc/passwd tinydebianlive/etc/passwd
    sudo cp -f /etc/shadow tinydebianlive/etc/shadow
    sudo sh -c "echo 'td ALL=(ALL) ALL' >> tinydebianlive/etc/sudoers"
    sudo mkdir -p tinydebianlive/home/td
    sudo chown -R td:users tinydebianlive/home/td
    sudo cp -f /home/td/.bashrc tinydebianlive/home/td/.bashrc
    
    sudo cp -f /usr/bin/vi tinydebianlive/usr/bin/vi
    sudo cp -f /bin/ping tinydebianlive/bin/ping
    sudo cp -f /usr/bin/dircolors tinydebianlive/usr/bin/dircolors
    
    sudo sh -c "echo 'auto lo eth0' >> tinydebianlive/etc/network/interfaces"
    sudo sh -c "echo 'allow-hotplug eth0' >> tinydebianlive/etc/network/interfaces"
    sudo sh -c "echo 'iface lo inet loopback' >> tinydebianlive/etc/network/interfaces"
    sudo sh -c "echo 'iface eth0 inet dhcp' >> tinydebianlive/etc/network/interfaces"
    
    # sudo chroot tinydebianlive apt-get -yqq --force-yes --no-install-recommends install net-tools iputils-ping wget openssh-server
    

    你也可以把用类似《一个fully retryable的rootbuild packer脚本,从0打造matecloudos(3):以lfs9观点看compiletc tools in advance》文中脚本的方法把环变和本机用户弄过去。
    sudo chroot tinydebianlive /usr/bin/env -i 加了LANGUAGE=en_US LANG=en_US.UTF-8 USER=td HOST=tinydebian PATH=/bin:/usr/bin:/sbin:/usr/sbin /bin/bash -c "
    echo $HOST > /etc/hostname;
    xxx
    "

    最后清理apt cache和一些asset files

    (sudo du -hs tinydebianlive,247MB)
    echo 'td' | sudo chroot tinydebianlive apt-get clean
    echo 'td' | sudo rm -rf tinydebianlive/usr/share/locale/*
    echo 'td' | sudo rm -rf tinydebianlive/usr/share/man/*
    echo 'td' | sudo rm -rf tinydebianlive/usr/share/doc/*
    echo 'td' | sudo rm -rf tinydebianlive/var/log/*
    echo 'td' | sudo rm -rf tinydebianlive/var/lib/apt/lists/*
    echo 'td' | sudo rm -rf tinydebianlive/var/cache/*
    #echo 'td' | sudo rm -rf tinydebianlive/etc/rc*
    (sudo du -hs tinydebianlive,这个步骤删掉了>100mb)
    

    打包测试:

    cd tinydebianlive; echo 'td' | sudo sh -c 'find . | cpio -o -H newc | gzip -9 > ../tinydebianlive-initramfs.gz'
    

    整个文件40-50mb。在系统启动grub时按c,linux (hd0,1)/boot/原来的linux,initrd (hd0,1)/home/td/tinydebianlive-initramfs.gz,成功!要注意的是,会有一些小概率启不动提示block vfs not mounted常见启不动报错的情况,多尝试几次。

    其实你也可以完全用busybox代替debian的大部分仅保留包支持,即用 busybox 处理debain的加载,甚至包括设备驱动的加载和热插拔,可以把tdl做得更小。

    做成硬盘系统

    上面跑完出来的是一个initramfs initrd,还要加入一个释放到硬盘的过程,形如《利用增强tinycorelinux remaster tool打造你的硬盘镜像及一种让tinycorelinux变成Debian install体的设想》中的preparehd那样

    把initrd转到/变成硬盘系统其实属于lfs的初级内容。主要工作是要改造的是initramfs中的那个init和处理二个rootfs(释放到硬盘中的那个initramfs拷贝不需要init,注意分辨,你也可以tar -C /tmp/cproot -cvf - . | tar -C /mnt -xvf - #表示将/tmp/cproot目录下所有文件打包,然后解压到/mnt,这条命令逻辑做到init中免去释放,tc就是这样做的),但这里涉及到一些至关重要的认识与问题:

    1)是,基于ramdisk 的initrd与基于ramfs的initramfs的区别,前者是一个设备支持privot_root和卸载,后者是一个tmpfs仅支持switch_root不支持privot_root和umount。(在这里你可以把privotroot,switchroot想象成chroot的高级版本用于rootfs init)。initramfs为了采用跟initrd一样的方式(1,删除原rootfs,2,mount -o move /dev/,/sys/,/proc/,/tmp/并chroot,3,重设/dev/console并执行新init)达到转到新的rootfs的目的,于是发明了switch_root,它自动处理1,2,3。所以并不需要太多工作(比如mount -o move手动转移/dev/,/sys/,/proc一次)
    注:经典的lfs教程和过程中往往有简单静态的测试环境假设,或者mount -o bind /dev,它有遮盖目标作用,或者move,move是转移。

    1. 是,改造init的工作往往直接用mount -t extxxx /dev/xxx /mnt/xxx,exec /sbin/switch_root /mnt/xxx /sbin/init这二句代替init末尾的exec /sbin/init这样的套路,(这里就隐含了假设的东西:因为init中分区写死在init脚本中了,所以,1,你不需要向cmdline传统root=/dev/xxx,2,也不需要/etc/fstab写入静态配置/dev/,/sys/,/proc/和目标分区/newxxx/的mount项)
      注:经典的lfs教程和过程中往往就使用了这样的方法,而现实情况(产生设备号,识别分区可能会比较复杂和动态化)往往不一样。

    3)是,对于2,init中会使用busybox写udev -s。(这条需要在exec switch前生效产生mount -t /dev/xxx的可用的设备号),否则会发生“init not tainted,switch_root not tainted”之类让你感觉莫名期妙的东西,但实际上,这里原因就是实际上就是mount不成功没找到,我们现在用的正是ramfs,我们这里的initramfs中的/dev是udev动态生成的,盘符不可能是静态配置在/dev中和fstab的,因此也需要在init中exec switch_root之前就让/dev中的mount targetee设备生效:

    为调试,你完全可以先在initramfs中的init写exec /bin/bash,进入initramfs打exec /sbin/init命令作测试(这里会提示没有控制终端只有内核/dev/console,而可以登录,带jobcontrol的正常终端是必须tty模拟的),从这开始调试,发现mount目标到/mnt/xxx是不成功的,而执行/sbin/init后执行了/etc/rcS.d/中一系列脚本才在/dev/中出现了mount目标的设备号(/etc/rcS.d/S02udev start,这个是最关键的脚本,执行后,测试exec switch_root才成功),

    于是这三条替换命令是:

    (mkdir /mnt/sysroot)这条可以事先做好在initramfs中
    然后是init中代替exec /sbin/init的这几条:
    /etc/rcS.d/S02udev start
    mount -t ext4 /dev/sdb1 /mnt/sysroot    (视你释放到的硬盘分区而定)
    exec /sbin/switch_root /mnt/sysroot /sbin/init
    

    成功进入硬盘系统!

    做成系统与包分离的tdl live

    当然也可以像tc一样,不用硬盘逻辑,将占据此发行版主体的包部分作为live加载部分,利用容器联合文件系统的思路独立出去+动态加载进来:

    在前面我们不断讲过用容器思路解决OS应用沙盒的问题,免脏的原理是利用应用沙盒,这里是利用系统沙盒,将系统和数据(要写入到系统中的数据,用户数据)分离。免去我们一次次因为装太多软件导致系统变慢弄脏重新装机的需要。。

    slax正是这样一种live系统和live工具,Slax Linux 9.2.1 不再基于 Slackware,现已切换至基于 Debian 的最新稳定版 Stretch。因此,Slax Linux 也将采用 APT 软件包管理工具和 Systemd 这款 init 程序。尽管新版本已经基于 Debian GNU/Linux 9.2.1 “Stretch”,但依然保留 Slackware 的前缀名字。这款系统的容量依然保持了轻量设计,Slax 9.2.1 的 64 位 live ISO 镜像只有 208MB。 ------ 但实际上,这些都是squashfs包,解包有1G多都说不定。也不小。它支持把整个系统当成一个子目录,所以我们从《子目录分离的linux》开始的就不用了,除非用于纯粹的硬盘安装需要子目录化。

    它的原理是跟tc一样,Having the temporary root filesystem in initramfs is not ideal, since it doesn't support pivot_root system call - an important operation which will be used later in the boot up process. We need to switch from initramfs to something else. To do that, the temporary init firstly mounts a tmpfs filesystem over /m, moves all files and directories in there including the init script itself, and uses switch_root to make this tmpfs /m the new root and to restart the init itself from there too. Blue star denotes the directory which is moved.

    他好像还搞了个linux-live.org,它的sb包是on-the-fly savechange制作的,类似快照commit。因此它自己不用维护一个类似tce的仓库。tc与slax区别是一个是软件库打包,一个是巨打包(core.gz,xorg,desktop,etc..),所以,要是这样的live os能像tc mount tcz一样直接支持mount deb作为包就好了。

    但实际上deb,systemd,容器这些,远没有tinycorelinux的"plain raw" 的tce,Slackwarepkg对人的亲和。否则我们也不必《在tc上安装buildkit.tcz,vscode.tcz,打通vscodeonline与openfaas模拟cloudbase打造碎片化编程开发部署环境》搞一套instant commit,容器的持续提交与构建很不原生。

    我把这种宏静态打包列为跟udeb,deb,并列的东西,分成pool/udeb,pool/deb,pool/ldeb放进我自己的镜像中

    然而,如果数据和系统可以做到原生分开,符合用户习惯,像群晖一样设置/volume1,系统存储中不混入任何应用和用户数据,也是不错的。


    debian存在就是因为它的包格式,可惜deb本身不是一开始定位于类tc的unionfs包,当然业界也有paraya(2008年左右存在),slax这种

    说回我们的目标,用类似《利用增强tinycorelinux remaster.....变成Debian install体的设想》tc remaster.sh的方法来使得pebuilder.sh变成dibuilder.sh(packer和tc remaster都是以iso为模板的),使得可以在通用linux上代替debootstrap的使用。我们看到minbase的包,就有底发明pebuilder了。因为peubilder就是通用linux版的debootstrap虽然功能没它强大,但比它灵活。可以通过基本的ar解压deb包组装系统代替debootstrap,或完全可以借助debootstrap的代码比如解析镜像indies部分。

    我们还要将其打包其mini.iso,然后以此为基础和模板。毕竟不能事事chroot,还得有一个基本可用的mini iso作为模板才好。

    我们未来还要自定义那个defconf界面,将pebuilder dd时那个进程显示出来。貌似它在usr/share/perl5/Debconf/FrontEnd/Dialog.pm

    还有一类debian下构建应用的工具,pbuilder(personal Debian package builder)是ubuntu环境下维护debian包的专业工具,能够为每个deb包创建纯净的编译构建环境,自动解析和安装依赖包,并且不污染宿主系统。

  • 相关阅读:
    Linux常用命令
    Linux静态函数库与动态函数库
    解决MySQL5.7的表无法插入中文的问题
    MySQL与postgreSQL在left join查询时的区别
    《刻意练习》读书笔记
    在Golang中实现与Python装饰器类似功能的方法
    项目中使用进程内缓存的一些经验及注意事项
    Golang中使用recover捕获panic的操作及遇到的一个坑
    Python与Golang中给列表中字典按照某个key排序的实现
    浅谈Python与Golang中的“延迟绑定机制”
  • 原文地址:https://www.cnblogs.com/minlearn/p/14221236.html
Copyright © 2011-2022 走看看