本文关键字:initrd多个gz,将td弄成tdpe和tdpanel,将dipe弄成*dd url,不死的boot配mian zang免脏的os:slax,can be in a rom flash,自己发明一个tinycorelinux
pebuilder.sh是一个利用debianinstall cd进行remaster打包的脚本,在《把DI当online packer用:利用installnet制作一个云装机packerpe》1,2和《利用onedrive加packerpebuilder实现本地网络统一装机》中,我们多次重构过这个脚本。最近的《将pebuilder变成dibuilder.sh,将di tools集入boot层(1)(2)》中我们陆续讲到了其原理并修补了它,并做了一些新的工作,最终是为了将dibuilder.sh发展成为一个支持normal debian os打包和debian live netinstall os打包的脚本(其中对于后者的支持已经相当好)。
其中本文继续讲述这个系列的第三部分:在(1)建立的一个基础的可供日照后remaster的最小包:td-initrd.gz的基础上,利用dibuilder.sh打造原来《一种混合包管理和容器管理方案,及在tinycorelinux上安装containerd和openfaas》《在tc上安装buildkit.tcz,vscode.tcz,打通vscodeonline与openfaas模拟cloudbase打造碎片化编程开发部署环境》中用tc实现的minstackos,解决上面第一段所述目标中dibuilder对于前者normal debian os的支持部分
不废话,直接上脚本,脚本整合为四个大流程,prepare prerequisites,prepare Essentials,prepare miscs,finishing phase,除了prepare prerequisites不用提其它会依次提到(以最近一次的脚本修改结果为参考讲解):
前置改动:
把原来的tmpDDURL抽象掉,以及原来的IncPkgrepo->GENMIRRORBAK也抽象掉,提出mode,target二个新变量,这是新的全局变量,
export tmpMODE='0' #DI?TD?
export tmpTARGET='' #dimirror,dsm61715284(di),winsrvcore2019(di),deepin20(di),minstackos(td)
export tmpINSTANTWITHOUTVNC='0'
export tmpWORD=''
export ipAddr=''
export ipMask=''
export ipGate=''
export myMirror='http://10.211.55.2:8000/mirrors'
export UNKNOWHW='0'
export UNVER='6.4'
这样的目的很清楚:正是为了能使dibuilder同时容纳di,td式remaster,,mode取值0,1就是支持分别从di-initrd.gz和td-initrd.gz remaster的变量,而target可以是dimirror(原来的GENMIRRORBAK:udeb package.gz所有条目和整个仓库打包),dsm61715284,winsrvcore2019,deepin20(这三都是原来的ddurl+di remaster)以及新的minstackos(它不是基于di而是基于td)
这二变量其实保留target在整个脚本中用于判断和分支就逻辑足够,但是不够逻辑清晰,所以增加的mode一层用来区别“5个target,3个是mode di,1个是mode td”
另,注意到我的mirror设置为不带debian后缀是为了稍后其也能表达同域下的target image gz as ddurl,如tmpDDURL=$myMirror/$tmpTARGET".gz",稍后的MIRROR=$(Select1stValidMirrorFrom3 $myMirror"/debian")和preseed中的mirror host/dir也是$myMirror,/debian处理
接下来是输入参数判断,可以看到case判断嵌套,mode和target联动,默认就是原来的mode0+ddurl target,targets中那些be prefined的一部分只是ddurl局变的封装,也支持raw http式的ddurl,当然,也支持dimirror和minstackos这二无关ddurl局变的特例。
while [[ $# -ge 1 ]]; do
case $1 in
-m|--mode)
shift
tmpMODE="$1"
shift
;;
-t|--target)
shift
tmpTARGET="$1"
tmpDDURL=''
case $tmpTARGET in
dimirror) ;;
winsrvcore2019) tmpDDURL=$myMirror/$tmpTARGET".gz" ;;
dsm61715284) tmpDDURL=$myMirror/$tmpTARGET".gz" ;;
deepin20) tmpDDURL=$myMirror/$tmpTARGET".gz" ;;
minstackos) tmpMODE='1' ;;
在unix界,0是正确,1是异常。所以eq 0是判断的正确面。
*) echo "$tmpTARGET" |grep -q '^http://\|^ftp://\|^https://';[[ $? -eq '0' ]] && tmpDDURL=$tmpTARGET || echo "target not supported";exit 1 ;;
esac
shift
;;
.......
新的全局变量给原来脚本只有一种di+ddurl mode+target的原分支带来一些改变,如:
echo -en "checking deps ......:"
if [[ "$tmpTARGET" == 'dimirror' ]] && [[ "$tmpMODE" == '0' ]]; then
CheckDependence wget,ar,awk,grep,sed,cut,cat,cpio,curl,gzip,find,dirname,basename,md5sum,sha1sum,sha256sum;
else
CheckDependence wget,ar,awk,grep,sed,cut,cat,cpio,curl,gzip,find,dirname,basename;
fi
还有主体doremaster处(这也是prepare Essentials开始的地方):原来的buildrepo也改为了function doremaster(),意思更明确,同时,原来函数外的 echo -e "Downloading basic kernel and rootfs files from: [\033[32m ${MIRROR}/xxx.gz \033[0m]\n"也被放进了函数内部。逻辑布局更聚集合理(3 Downloading all in oneplace),同样也有关于mode+target的分支判断:
function doremaster(){
echo -e "Downloading basic kernel and rootfs files from: [\033[32m ${MIRROR}/xxx.gz \033[0m]\n"
IncFirmware='0'
wget --no-check-certificate -qO '/boot/vmlinuz' "${MIRROR}/linux"
[[ $? -ne '0' ]] && echo -ne "\033[31mError! \033[0mDownload 'vmlinuz' for \033[33mdebian\033[0m failed! \n" && exit 1
if [[ "$tmpMODE" == '0' ]]; then
wget --no-check-certificate -qO '/boot/initrd.img' "${MIRROR}/di-initrd.gz"
[[ $? -ne '0' ]] && echo -ne "\033[31mError! \033[0mDownload 'initrd.img' for \033[33mdebian\033[0m failed! \n" && exit 1
else
wget --no-check-certificate -qO '/boot/initrd.img' "${MIRROR}/td-initrd.gz"
[[ $? -ne '0' ]] && echo -ne "\033[31mError! \033[0mDownload 'initrd.img' for \033[33mdebian\033[0m failed! \n" && exit 1
fi
bakdir='/tmp/boot/var/log/debian'
if [[ "$tmpTARGET" == 'dimirror' ]] && [[ "$tmpMODE" == '0' ]]; then
mkdir -p "$bakdir"
cp "/boot/initrd.img" "${bakdir}/di-initrd.gz"
cp "/boot/vmlinuz" "${bakdir}/linux"
elif [[ "$tmpTARGET" == 'minstackos' ]] && [[ "$tmpMODE" == '1' ]]; then
mkdir -p "$bakdir"
cp "/boot/initrd.img" "${bakdir}/td-initrd.gz"
cp "/boot/vmlinuz" "${bakdir}/linux"
fi
......
被加进OPTPKGS的minstackos条目:
declare -A OPTPKGS
OPTPKGS=(
......
["faasd1"]="pool/minstack/containerd.deb"
["faasd2"]="pool/minstack/buildkit.deb"
["faasd3"]="pool/minstack/faasd.deb"
["fmtfaasd"]="xz"
["binfaasd"]=""
["vscodeonline1"]="pool/minstack/vscodeonline.deb"
["fmtvscodeonline"]="xz"
["binvscodeonline"]=""
这些deb都是原来tcz加了一个极简DEBIAN/control文件直接dpkg -b打包来的。不能apt-get install安装,也没有内部依赖设定。不过刚好适合dibuilder.sh这种没有debootstrap式递归依赖处理的。仅用来支持minstack target够用就好。
if [[ "$tmpTARGET" == 'dimirror' ]] && [[ "$tmpMODE" == '0' ]]; then
echo -e "Downloading full udebs pkg files from ..... [\033[32m ${MIRROR}/dists/jessie/main/debian-installer/binary-amd64/Packages.gz \033[0m]\n"
......
else
echo -e "Downloading full udebs pkg files from ..... [\033[32m skipping!! \033[0m]\n"
fi
echo -e "Downloading optional/necessary deb pkg files from ...... [\033[32m ${MIRROR}/dists/jessie/main/binary-amd64/Packages.gz \033[0m]\n";
.......
}
if [[ "$tmpMODE" == '0' ]]; then
doremaster libc,common,wgetssl;
elif [[ "$tmpTARGET" == 'minstackos' ]] && [[ "$tmpMODE" == '1' ]]; then
doremaster faasd,vscodeonline;
fi
sleep 2s
这里的工作其实就是提高了一些抽象到mode+target组合,并开辟了一些新的流程判断。并没有给dibuilder带来改观的变化,不过足够支持minstackos remaster的完成而已。(到这里也是prepare Essentials结束,prepare misc开始的地方)
后置改变
prepare misc包括prepare net,prepare bootload,prepare preseed,我们将产生preseed的地方提前到net后,bootloader前,是因为grub的准备涉及到前二者,比如,未来可能我们为了让ddurl可以被定制,让preseed file作为url放在linux cmdline中作为auto url。这样往grubcmd加add options,boot options,形如net给grub加的:auto=true priority=critical interface=auto netcfg/no_default_route=true preseed/url=http://192.168.100.1/preseed.cfg ,grub应该放在最后。
\r是为了在......后输出CalcDDExt $tmpDDURL的结果
echo -en "\rthe preseed ......."
UNZIP=''
IMGSIZE=''
function CalcDDExt(){
if [[ -n "$1" ]]; then
echo "$1" |grep -q '^http://\|^ftp://\|^https://';
[[ $? -ne '0' ]] && echo 'No valid URL in the DD argument,Only support http://, ftp:// and https:// !' && exit 1;
IMGHEADERCHECK="$(curl -IsL "$1")";
IMGTYPECHECK="$(echo "$IMGHEADERCHECK"|grep -E -o '200|302'|head -n 1)" || IMGTYPECHECK='0';
.......
}
if [[ "$tmpMODE" == '0' ]]; then
CalcDDExt $tmpDDURL;
# wget -qO- '$DDURL' |gzip -dc |dd of=$(list-devices disk |head -n1)|(pv -s \$IMGSIZE -n) 2&>1|dialog --gauge "progress" 10 70 0
[[ "$UNZIP" == '0' ]] && PIPECMDSTR='wget -qO- '$tmpDDURL' |dd of=$(list-devices disk |head -n1)';
[[ "$UNZIP" == '1' ]] && PIPECMDSTR='wget -qO- '$tmpDDURL' |tar zOx |dd of=$(list-devices disk |head -n1)';
[[ "$UNZIP" == '2' ]] && PIPECMDSTR='wget -qO- '$tmpDDURL' |gzip -dc |dd of=$(list-devices disk |head -n1)';
cat >/tmp/boot/preseed.cfg<<EOF
d-i preseed/early_command string anna-install
......
sbin/reboot
EOF
else
echo -e "[\033[32m skipping!! \033[0m]"
fi
echo -e "the grub loader"
......
然后是prepare misc的结束,finishing phase的开始(里面有unpacking):
.......
sed -i '$a\\n' /tmp/grub.new;
fi
echo -e "\n\n\033[36m# Finishing \033[0m\n"
[[ "$tmpINSTANTWITHOUTVNC" == '0' ]] && {
GRUBPATCH='0';
if [[ "$LoaderMode" == "0" ]]; then
[ -f '/etc/network/interfaces' -o -d '/etc/sysconfig/network-scripts' ] || {
echo "Error, Not found interfaces config.";
exit 1;
}
sed -i ''${INSERTGRUB}'i\\n' $GRUBDIR/$GRUBFILE;
sed -i ''${INSERTGRUB}'r /tmp/grub.new' $GRUBDIR/$GRUBFILE;
sed -i 's/timeout_style=hidden/timeout_style=menu/g' $GRUBDIR/$GRUBFILE;
sed -i 's/timeout=[0-9]*/timeout=30/g' $GRUBDIR/$GRUBFILE;
[[ -f $GRUBDIR/grubenv ]] && sed -i 's/saved_entry/#saved_entry/g' $GRUBDIR/grubenv;
fi
echo -e "unpacking ......"
cd /tmp/boot;
COMPTYPE="gzip";
CompDected='0'
for ListCOMP in `echo -en 'gzip\nlzma\nxz'`
do
.......
$UNCOMP < /tmp/$NewIMG | cpio --extract --verbose --make-directories --no-absolute-filenames >>/dev/null 2>&1
[[ -f '/boot/firmware.cpio.gz' ]] && {
gzip -d < /boot/firmware.cpio.gz | cpio --extract --verbose --make-directories --no-absolute-filenames >>/dev/null 2>&1
}
if [[ "$tmpMODE" == '0' ]]; then
sleep 2s && echo -en "fix minios in the preseed file\n"
这里是原来preseed开始的地方,这里上提作为finishing->sub过程的unpacking之后fix minios in preseed file,仅保留fix部分:
[[ "$LoaderMode" != "0" ]] && AutoNet='1'
[[ "$setNet" == '0' ]] && [[ "$AutoNet" == '1' ]] && {
sed -i '/netcfg\/disable_autoconfig/d' /tmp/boot/preseed.cfg
sed -i '/netcfg\/dhcp_options/d' /tmp/boot/preseed.cfg
sed -i '/netcfg\/get_.*/d' /tmp/boot/preseed.cfg
sed -i '/netcfg\/confirm_static/d' /tmp/boot/preseed.cfg
}
#[[ "$GRUBPATCH" == '1' ]] && {
# sed -i 's/^d-i\ grub-installer\/bootdev\ string\ default//g' /tmp/boot/preseed.cfg
#}
#[[ "$GRUBPATCH" == '0' ]] && {
# sed -i 's/debconf-set\ grub-installer\/bootdev.*\"\;//g' /tmp/boot/preseed.cfg
#}
sed -i '/user-setup\/allow-password-weak/d' /tmp/boot/preseed.cfg
sed -i '/user-setup\/encrypt-home/d' /tmp/boot/preseed.cfg
#sed -i '/pkgsel\/update-policy/d' /tmp/boot/preseed.cfg
#sed -i 's/umount\ \/media.*true\;\ //g' /tmp/boot/preseed.cfg
sleep 2s && echo -en "make a safe wget wrapper to inc --no-check-certificate\n"
......
sleep 2s && echo -en "packaging all up .....\n"
find . | cpio -H newc --create --quiet | gzip -9 > /boot/initrd.img;
[[ "$tmpMODE" == '1' ]] && echo -en "packaging finished,and all done! auto reboot after 9999s...(if needed, you can press ctrl c to interrupt to bak the repodir under tmp/boot/, then manually reboot to continue)" && sleep 9999s
rm -rf /tmp/boot;
}
[[ "$tmpINSTANTWITHOUTVNC" == '1' ]] && {
......
如果让preseed不内置,而作为一个独立的url放在grub commandline,那么可以做更多*的事情,比如:
1,在pressed中自动产生一个boot区,自动完成《将pebuilder变成dibuilder.sh,将di tools集入boot层(2)》做的事情。
2,做那种带cdrom file:// as deb source的live install cd
当然这些在cat <<内置preseed中也可以做,只是调试出来比较麻烦。没有分出去调试方便。
发明minstack live os
我们利用上述脚本td mode+minstack target跑出来的是一个巨大的initramfs,还要加入一个释放到硬盘的过程,形如《利用增强tinycorelinux remaster tool打造你的硬盘镜像及一种让tinycorelinux变成Debian install体的设想》中的preparehd那样,当然也可以像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制作的。因此它自己不用维护一个类似tce的仓库。tc与slax区别是一个是软件库打包,一个是巨打包(core.gz,xorg,desktop,etc..)
但实际上deb,systemd,容器这些,远没有tinycorelinux的"plain raw" 的tce,Slackwarepkg对人的亲和。否则我们也不必《在tc上安装buildkit.tcz,vscode.tcz,打通vscodeonline与openfaas模拟cloudbase打造碎片化编程开发部署环境》搞一套instant commit,容器的持续提交与构建很不原生。
然而,如果数据和系统可以做到原生分开,符合用户习惯,像群晖一样,系统存储中不混入任何应用和用户数据,也是不错的。