diff --git a/debian.cfg b/debian.cfg index 24b8667..ef6b449 100644 --- a/debian.cfg +++ b/debian.cfg @@ -25,10 +25,10 @@ d-i mirror/country string manual # B.4.5. 帐号设置 d-i passwd/make-user boolean false -# 单纯为了跳过设置,实际上是在 partman/early_command 里设置密码,preseed/early_command 无法设置密码 # 注意如果用 ssh key 后面还要删除密码 -d-i passwd/root-password password '' -d-i passwd/root-password-again password '' +# d-i passwd/root-password password '' +# d-i passwd/root-password-again password '' +# d-i passwd/root-password-crypted password '' # kali 需要下面这行,否则会提示输入用户名 d-i passwd/root-login boolean true @@ -63,6 +63,9 @@ d-i partman-efi/non_efi_system boolean true # 选择 true 就一直死循环 d-i partman-basicfilesystems/no_swap boolean false +# 分区大小计算 +# https://salsa.debian.org/installer-team/partman-base/-/blob/master/lib/base.sh + # 最小值 膨胀权重 最大值 # https://salsa.debian.org/installer-team/partman-auto/-/blob/master/recipes/atomic?ref_type=heads # https://salsa.debian.org/installer-team/partman-auto/-/blob/master/recipes-amd64-efi/atomic?ref_type=heads @@ -99,26 +102,128 @@ d-i pkgsel/upgrade select none d-i grub-installer/force-efi-extra-removable boolean true # B.4.12. 完成安装 -d-i finish-install/reboot_in_progress note +# 由下面的 hold 2 设置 +# d-i finish-install/reboot_in_progress note # B.4.13. 预置其他的软件包 # 其他设置 # d-i anna/standard_modules boolean false # d-i anna/choose_modules string network-console -# d-i network-console/password password 123@@@ -# d-i network-console/password-again password 123@@@ +# d-i network-console/password password '' +# d-i network-console/password-again password '' # B.5.1. 安装过程中运行用户命令 # 注意所有命令都会合并成一行命令 # 最后的 true; \ 没什么用,只是让 vscode 代码高亮不报错误 +# debian 11+ 才有 websocketd + # 有 /cdrom/simple-cdd 才安装 simple-cdd-profiles # 不然安装时 control 脚本会报错: # Loading simple-cdd-profiles failed for unknown reasons + +# 未下载的组件,无法用 debconf-set,需要用 debconf-set-selections + +# https://salsa.debian.org/installer-team/network-console/-/blob/master/debian/network-console.postinst?ref_type=heads +# https://salsa.debian.org/installer-team/user-setup/-/blob/master/user-setup-apply?ref_type=heads + +# 此时还没有配置源,anna-install 会在配置完源后再安装 d-i preseed/early_command string true; \ - if [ -d /cdrom/simple-cdd ]; then anna-install simple-cdd-profiles; fi + for str in $(grep -wo "extra_[^ ]*" /proc/cmdline | sed 's/^extra_//'); do eval "$str"; done; \ + + di(){ \ + echo "d-i $*" >/tmp/selections.cfg; \ + echo "d-i $*" >>/tmp/selections.cfg.all; \ + debconf-set-selections /tmp/selections.cfg; \ + rm -f /tmp/selections.cfg; \ + }; \ + + run_as_service_with_screen() { \ + if ! [ -f /etc/screenrc.bak ]; then \ + cp /etc/screenrc /etc/screenrc.bak; \ + fi; \ + true >/etc/screenrc; \ + screen sh -c 'while true; do pidof ${1##*/} || "$@"; sleep 5; done' _ "$@"; \ + cp -f /etc/screenrc.bak /etc/screenrc; \ + }; \ + + if [ "$hold" = 1 ]; then \ + di auto-install/enable boolean false; \ + di debconf/priority select low; \ + di partman/early_command string; \ + else \ + { \ + echo 'Reinstalling...'; \ + echo 'Option 1. View logs:'; \ + echo ' tail -fn+1 /var/log/syslog'; \ + echo 'Option 2. Attach to the installer:'; \ + echo ' TERM=screen screen -xp1'; \ + } >>/etc/motd; \ + mem=$(grep ^MemTotal: /proc/meminfo | { read -r _ y _; echo "$((y / 1024))"; }); \ + if command -v websocketd && [ "$mem" -ge 400 ]; then \ + for _ in {1..10}; do \ + if wget "$confhome/logviewer.html" -O /tmp/index.html; then \ + break; \ + fi; \ + sleep 5; \ + done; \ + if [ -z "$web_port" ]; then \ + web_port=80; \ + fi; \ + run_as_service_with_screen websocketd --port 80 --loglevel=fatal --staticdir=/tmp \ + sh -c "tail -fn+0 /var/log/syslog | tr '\r' '\n' | grep -Fiv -e password -e token" ; \ + fi; \ + fi; \ + + if ! [ "$hold" = 2 ]; then \ + di finish-install/reboot_in_progress note; \ + fi; \ + + if [ -s /configs/ssh_keys ]; then \ + di passwd/root-password-crypted password "''"; \ + else \ + di passwd/root-password-crypted password "$(cat /configs/password-linux-sha512)"; \ + fi; \ + + mkdir -p /etc/ssh; \ + true >/etc/ssh/sshd_config; \ + if [ -s /configs/ssh_keys ]; then \ + (umask 077; mkdir -p /.ssh; cat /configs/ssh_keys >/.ssh/authorized_keys); \ + else \ + echo "PermitRootLogin yes" >>/etc/ssh/sshd_config; \ + fi; \ + if [ -n "$ssh_port" ] && ! [ "$ssh_port" = 22 ]; then \ + echo "Port $ssh_port" >>/etc/ssh/sshd_config; \ + fi; \ + grep -qs ^root: /etc/shadow || echo "root:$(cat /configs/password-linux-sha512):1:0:99999:7:::" >>/etc/shadow; \ + grep -qs ^nogroup: /etc/group || echo "nogroup:*:65534:" >>/etc/group; \ + grep -qs ^sshd: /etc/passwd || echo "sshd:*:100:65534::/run/sshd:/bin/false" >>/etc/passwd; \ + mkdir -p /run/sshd; \ + chmod 0755 /run/sshd; \ + ssh-keygen -A; \ + run_as_service_with_screen /usr/sbin/sshd -D; \ + + if [ -s /configs/frpc.toml ]; then \ + url=$(sh /get-frpc-url.sh linux); \ + mkdir -p /usr/local/bin; \ + mkdir -p /usr/local/etc/frpc; \ + for _ in {1..10}; do \ + if wget -O- "$url" | tar xz "*/frpc" -O >/usr/local/bin/frpc; then \ + break; \ + fi; \ + sleep 5; \ + done; \ + rm -f /frpc.tar.gz; \ + chmod a+x /usr/local/bin/frpc; \ + cp /configs/frpc.toml /usr/local/etc/frpc/; \ + run_as_service_with_screen /usr/local/bin/frpc -c /usr/local/etc/frpc/frpc.toml; \ + fi; \ + + if [ -d /cdrom/simple-cdd ]; then \ + anna-install simple-cdd-profiles; \ + fi # debian 11 initrd 没有 xargs awk # debian 12 initrd 没有 xargs @@ -132,10 +237,11 @@ d-i partman/early_command string true; \ true >$postinst; \ swapfile=/target/swapfile; \ - mem=$(grep ^MemTotal: /proc/meminfo | { read -r _ y _; echo "$y"; }); \ - mem=$((mem / 1024)); \ + mem=$(grep ^MemTotal: /proc/meminfo | { read -r _ y _; echo "$((y / 1024))"; }); \ swap_size=$((512 - mem)); \ - [ $swap_size -gt 0 ] && echo "fallocate -l ${swap_size}M $swapfile; mkswap $swapfile; swapon $swapfile" >>$postinst; \ + if [ $swap_size -gt 0 ]; then \ + echo "fallocate -l ${swap_size}M $swapfile; mkswap $swapfile; swapon $swapfile" >>$postinst; \ + fi; \ echo "swapoff -a; rm -f $swapfile" >/usr/lib/finish-install.d/95swapoff; \ chmod a+x /usr/lib/finish-install.d/95swapoff; \ @@ -152,12 +258,15 @@ d-i partman/early_command string true; \ eths=$(cd /dev/netconf/ && ls); \ - sh /can_use_cloud_kernel.sh "$xda" $eths || debconf-set base-installer/kernel/image "$(debconf-get base-installer/kernel/image | sed 's/-cloud//')"; \ + if ! sh /can_use_cloud_kernel.sh "$xda" $eths; then \ + debconf-set base-installer/kernel/image "$(debconf-get base-installer/kernel/image | sed 's/-cloud//')"; \ + fi; \ - [ -d /sys/firmware/efi ] && debconf-set partman-auto/expert_recipe "$(debconf-get partman-auto/expert_recipe_efi)"; \ - [ -d /sys/firmware/efi ] || debconf-set partman-auto/expert_recipe "$(debconf-get partman-auto/expert_recipe_bios)"; \ - - debconf-set passwd/root-password-crypted "$(cat /configs/password-linux-sha512)"; \ + if [ -d /sys/firmware/efi ]; then \ + debconf-set partman-auto/expert_recipe "$(debconf-get partman-auto/expert_recipe_efi)"; \ + else \ + debconf-set partman-auto/expert_recipe "$(debconf-get partman-auto/expert_recipe_bios)"; \ + fi; \ true >/bin/os-prober @@ -188,17 +297,11 @@ d-i preseed/late_command string true; \ fi; \ if [ -s /configs/frpc.toml ]; then \ - url=$(sh /get-frpc-url.sh linux); \ - basename=$(echo "$url" | sed 's,.*/,,' | sed 's,\.tar\.gz,,'); \ mkdir -p /target/usr/local/bin; \ mkdir -p /target/usr/local/etc/frpc; \ - for i in {1..5}; do \ - wget -O /target/frpc.tar.gz "$url" && break; \ - done; \ - tar xzf /target/frpc.tar.gz "$basename/frpc" -O >/target/usr/local/bin/frpc; \ - rm -f /target/frpc.tar.gzx; \ + cp /usr/local/bin/frpc /target/usr/local/bin/; \ + cp /usr/local/etc/frpc/frpc.toml /target/usr/local/etc/frpc/; \ chmod a+x /target/usr/local/bin/frpc; \ - cp /configs/frpc.toml /target/usr/local/etc/frpc/; \ cp /frpc.service /target/etc/systemd/system/; \ in-target systemctl enable frpc; \ fi; \ diff --git a/reinstall.sh b/reinstall.sh index 0f0777c..6fc1997 100644 --- a/reinstall.sh +++ b/reinstall.sh @@ -11,7 +11,7 @@ confhome_cn=https://cnb.cool/bin456789/reinstall/-/git/raw/main DEFAULT_PASSWORD=123@@@ # 用于判断 reinstall.sh 和 trans.sh 是否兼容 -SCRIPT_VERSION=4BACD833-A585-23BA-6CBB-9AA4E08E0003 +SCRIPT_VERSION=4BACD833-A585-23BA-6CBB-9AA4E08E0004 # 记录要用到的 windows 程序,运行时输出删除 \r WINDOWS_EXES='cmd powershell wmic reg diskpart netsh bcdedit mountvol' @@ -280,11 +280,21 @@ get_function_content() { } insert_into_file() { - file=$1 - location=$2 - regex_to_find=$3 + local file=$1 + local location=$2 + local regex_to_find=$3 + shift 3 - line_num=$(grep -E -n "$regex_to_find" "$file" | cut -d: -f1) + if ! [ -f "$file" ]; then + error_and_exit "File not found: $file" + fi + + # 默认 grep -E + if [ $# -eq 0 ]; then + set -- -E + fi + + line_num=$(grep "$@" -n "$regex_to_find" "$file" | cut -d: -f1) found_count=$(echo "$line_num" | wc -l) if [ ! "$found_count" -eq 1 ]; then @@ -1242,6 +1252,7 @@ Continue? eval ${step}_vmlinuz=$mirror/linux eval ${step}_initrd=$mirror/initrd.gz eval ${step}_ks=$confhome/debian.cfg + eval ${step}_deb_mirror=$hostname/kali eval ${step}_udeb_mirror=$hostname/kali eval ${step}_codename=$codename eval ${step}_kernel=linux-image$flavour-$basearch_alt @@ -2275,6 +2286,10 @@ del_empty_lines() { sed '/^[[:space:]]*$/d' } +del_comment_lines() { + sed '/^[[:space:]]*#/d' +} + trim() { # sed -E -e 's/^[[:space:]]+//' -e 's/[[:space:]]+$//' sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' @@ -2998,7 +3013,11 @@ build_nextos_cmdline() { if [ $nextos_distro = alpine ]; then nextos_cmdline="alpine_repo=$nextos_repo modloop=$nextos_modloop" elif is_distro_like_debian $nextos_distro; then + # 设置分辨率为800*600,防止分辨率过高 ssh screen attach 后无法全部显示 + # iso 默认有 vga=788 + # 如果要设置位数: video=800x600-16 nextos_cmdline="lowmem/low=1 auto=true priority=critical" + # nextos_cmdline+=" vga=788 video=800x600" nextos_cmdline+=" url=$nextos_ks" nextos_cmdline+=" mirror/http/hostname=${nextos_udeb_mirror%/*}" nextos_cmdline+=" mirror/http/directory=/${nextos_udeb_mirror##*/}" @@ -3074,6 +3093,14 @@ mod_initrd_debian_kali() { sed -Ei 's,&&( onlink=),||\1,' etc/udhcpc/default.script # hack 2 + # 强制使用 screen + # shellcheck disable=SC1003,SC2016 + { + echo 'if false && : \' | insert_into_file lib/debian-installer.d/S70menu before 'if [ -x "$bterm" ]' -F + echo 'if true || : \' | insert_into_file lib/debian-installer.d/S70menu before 'if [ -x "$screen_bin" -a' -F + } + + # hack 3 # 修改 /var/lib/dpkg/info/netcfg.postinst 运行我们的脚本 netcfg() { #!/bin/sh @@ -3085,18 +3112,24 @@ mod_initrd_debian_kali() { # 运行 trans.sh,保存配置 db_progress INFO base-installer/progress/netcfg - sh /trans.sh + # 添加 || exit ,可以在 debian installer 不兼容 /trans.sh 语法时强制报错 + # exit 不带参数,返回值为 || 前面命令的返回值 + sh /trans.sh || exit db_progress STEP 1 + db_progress STOP } - # 直接覆盖 net-retriever,方便调试 - # curl -Lo /usr/lib/debian-installer/retriever/net-retriever $confhome/net-retriever - postinst=var/lib/dpkg/info/netcfg.postinst get_function_content netcfg >$postinst get_ip_conf_cmd | insert_into_file $postinst after ": get_ip_conf_cmd" # cat $postinst + # hack 4 + # 修改 udeb 依赖 + + # 直接覆盖 net-retriever,方便调试 + # curl -Lo /usr/lib/debian-installer/retriever/net-retriever $confhome/net-retriever + change_priority() { while IFS= read -r line; do if [[ "$line" = Package:* ]]; then @@ -3180,32 +3213,44 @@ EOF # 云内核没有 sata 模块,也没有内嵌,有一个 CONFIG_SATA_HOST=y,libata-$(CONFIG_SATA_HOST) += libata-sata.o # scsi-modules 默认安装(改成可选),包含 nvme.ko(+) 和各种虚拟化驱动(+) - download_and_extract_udeb() { - package=$1 - extract_dir=$2 + download_and_extract_deb() { + local type=$1 + local package=$2 + local extract_dir=$3 - # 获取 udeb 列表 - udeb_list=$tmp/udeb_list - if ! [ -f $udeb_list ]; then - # shellcheck disable=SC2154 - curl -L http://$nextos_udeb_mirror/dists/$nextos_codename/main/debian-installer/binary-$basearch_alt/Packages.gz | - zcat | grep 'Filename:' | awk '{print $2}' >$udeb_list + # shellcheck disable=SC2154 + case "$type" in + deb) + local mirror=$nextos_deb_mirror + local url=http://$mirror/dists/$nextos_codename/main/binary-$basearch_alt/Packages.gz + ;; + udeb) + local mirror=$nextos_udeb_mirror + local url=http://$mirror/dists/$nextos_codename/main/debian-installer/binary-$basearch_alt/Packages.gz + ;; + esac + + # 获取 deb/udeb 列表 + deb_list=$tmp/${type}_list + if ! [ -f $deb_list ]; then + curl -L "$url" | zcat | grep 'Filename:' | awk '{print $2}' >$deb_list fi - # 下载 udeb - curl -Lo $tmp/tmp.udeb http://$nextos_udeb_mirror/"$(grep -F /${package}_ $udeb_list)" + # 下载 deb/udeb + deb_path=$(grep -F "/${package}_" "$deb_list") + curl -Lo $tmp/tmp.deb http://$mirror/"$deb_path" if false; then # 使用 dpkg # cygwin 没有 dpkg install_pkg dpkg - dpkg -x $tmp/tmp.udeb $extract_dir + dpkg -x $tmp/tmp.deb $extract_dir else # 使用 ar tar xz # cygwin 需安装 binutils # centos7 ar 不支持 --output install_pkg ar tar xz - (cd $tmp && ar x $tmp/tmp.udeb) + (cd $tmp && ar x $tmp/tmp.deb) tar xf $tmp/data.tar.xz -C $extract_dir fi } @@ -3249,12 +3294,27 @@ EOF curl -Lo usr/share/keyrings/debian-archive-keyring.gpg https://deb.freexian.com/extended-lts/archive-key.gpg fi + # 提前下载 sshd + # 以便在配置下载源之前就可以启动 sshd + mkdir_clear $tmp/sshd + download_and_extract_deb udeb openssh-server-udeb $tmp/sshd + cp -r $tmp/sshd/* . + # 提前下载 fdisk # 因为 fdisk-udeb 包含 fdisk 和 sfdisk,提前下载可减少占用 mkdir_clear $tmp/fdisk - download_and_extract_udeb fdisk-udeb $tmp/fdisk + download_and_extract_deb udeb fdisk-udeb $tmp/fdisk cp -f $tmp/fdisk/usr/sbin/fdisk usr/sbin/ + # 下载 websocketd + # debian 11+ 才有 websocketd + if [ "$distro" = kali ] || + { [ "$distro" = debian ] && [ "$releasever" -ge 11 ]; }; then + mkdir_clear $tmp/websocketd + download_and_extract_deb deb websocketd $tmp/websocketd + cp -f $tmp/websocketd/usr/bin/websocketd usr/bin/ + fi + # >256M 或者当前系统是 windows if [ $ram_size -gt 256 ] || is_in_windows; then sed -i '/^pata-modules/d' $net_retriever @@ -3285,7 +3345,7 @@ EOF # 但反查也找不到 curl https://deb.debian.org/debian/dists/bookworm/main/Contents-udeb-amd64.gz | zcat | grep xen if [ -n "$extra_drivers" ]; then mkdir_clear $tmp/scsi - download_and_extract_udeb scsi-modules-$kver-di $tmp/scsi + download_and_extract_deb udeb scsi-modules-$kver-di $tmp/scsi relative_drivers_dir=lib/modules/$kver/kernel/drivers udeb_drivers_dir=$tmp/scsi/$relative_drivers_dir @@ -4454,13 +4514,18 @@ EOF get_function_content load_grubenv_if_not_loaded >$target_cfg # 原系统为 openeuler 云镜像,需要添加 --unrestricted,否则要输入密码 - del_empty_lines <"$os_dir/usr/local/bin/frpc" + tar xzf "$os_dir/frpc.tar.gz" "*/frpc" -O >"$os_dir/usr/local/bin/frpc" rm -f "$os_dir/frpc.tar.gz" chmod a+x "$os_dir/usr/local/bin/frpc"