core: 移动部分文件到 deprecated 目录

This commit is contained in:
bin456789
2026-06-19 10:53:30 +08:00
parent b35751bd72
commit 662e4d9eb5
10 changed files with 19 additions and 13 deletions
+185
View File
@@ -0,0 +1,185 @@
#!/bin/bash
# 修复 cloud-init 没有正确渲染 onlink 网关
set -eE
os_dir=$1
# 该脚本也会在 alpine live 下调用
# 防止在 alpine live 下运行 systemctl netplan 报错
systemctl() {
if systemd-detect-virt --chroot; then
return
fi
command systemctl "$@"
}
netplan() {
if systemd-detect-virt --chroot; then
return
fi
command netplan "$@"
}
insert_into_file() {
file=$1
location=$2
regex_to_find=$3
if [ "$location" = head ]; then
bak=$(mktemp)
cp "$file" "$bak"
cat - "$bak" >"$file"
else
line_num=$(grep -E -n "$regex_to_find" "$file" | cut -d: -f1)
found_count=$(echo "$line_num" | wc -l)
if [ ! "$found_count" -eq 1 ]; then
return 1
fi
case "$location" in
before) line_num=$((line_num - 1)) ;;
after) ;;
*) return 1 ;;
esac
sed -i "${line_num}r /dev/stdin" "$file"
fi
}
fix_netplan_conf() {
# 修改前
# gateway4: 1.1.1.1
# gateway6: ::1
# 修改后
# routes:
# - to: 0.0.0.0/0
# via: 1.1.1.1
# on-link: true
# routes:
# - to: ::/0
# via: ::1
# on-link: true
conf=$os_dir/etc/netplan/50-cloud-init.yaml
if ! [ -f "$conf" ]; then
return
fi
# 判断 bug 是否已经修复
if grep -q 'on-link:' "$conf"; then
return
fi
# 获取网关
gateways=$(grep 'gateway[4|6]:' "$conf" | awk '{print $2}')
if [ -z "$gateways" ]; then
return
fi
# 获取缩进
spaces=$(grep 'gateway[4|6]:' "$conf" | head -1 | grep -o '^[[:space:]]*')
{
# 网关头部
cat <<EOF
${spaces}routes:
EOF
# 网关条目
for gateway in $gateways; do
# debian 11 的 netplan 不支持 to: default
case $gateway in
*.*) to='0.0.0.0/0' ;;
*:*) to='::/0' ;;
esac
cat <<EOF
${spaces} - to: $to
${spaces} via: $gateway
${spaces} on-link: true
EOF
done
} | insert_into_file "$conf" before 'match:'
# 删除原来的条目
sed -i '/gateway[4|6]:/d' "$conf"
# 重新应用配置
if command -v netplan && {
systemctl -q is-enabled systemd-networkd || systemctl -q is-enabled NetworkManager
}; then
netplan apply
fi
}
fix_networkd_conf() {
# 修改前 gentoo
# [Route]
# Gateway=1.1.1.1
# Gateway=2602::1
# 修改前 arch
# [Route]
# Gateway=1.1.1.1
#
# [Route]
# Gateway=2602::1
# 修改后
# [Route]
# Gateway=1.1.1.1
# GatewayOnLink=yes
#
# [Route]
# Gateway=2602::1
# GatewayOnLink=yes
if ! confs=$(ls "$os_dir"/etc/systemd/network/10-cloud-init-*.network 2>/dev/null); then
return
fi
for conf in $confs; do
# 判断 bug 是否已经修复
if grep -q '^GatewayOnLink=' "$conf"; then
return
fi
# 获取网关
gateways=$(grep '^Gateway=' "$conf" | cut -d= -f2)
if [ -z "$gateways" ]; then
return
fi
# 删除原来的条目
sed -i '/^\[Route\]/d; /^Gateway=/d; /^GatewayOnLink=/d' "$conf"
# 创建新条目
for gateway in $gateways; do
echo "
[Route]
Gateway=$gateway
GatewayOnLink=yes
"
done >>"$conf"
done
# 重新应用配置
# networkctl reload 不起作用
if systemctl -q is-enabled systemd-networkd; then
systemctl restart systemd-networkd
fi
}
# ubuntu 18.04 cloud-init 版本 23.1.2,因此不用处理
# debian 10/11 云镜像原本用 ifupdown + resolvconf,脚本改成用 netplan + networkd/resolved
# debian 12 云镜像: netplan + networkd/resolved
# 23.1.1 修复
fix_netplan_conf
# arch: networkd/resolved
# gentoo: networkd/resolved
# 24.2 修复
# 只需对云镜像处理
# 因为普通安装用的是 alpine 的 cloud-init,版本够新,不用处理
fix_networkd_conf
+36
View File
@@ -0,0 +1,36 @@
#cloud-config
datasource_list: [None]
timezone: Asia/Shanghai
disable_root: false
ssh_pwauth: true
users:
- name: root
lock_passwd: false
chpasswd:
expire: false
# <= cloud-init 22.2.x 需要
list: |
root:@PASSWORD@
users:
- name: root
password: "@PASSWORD@"
type: hash
runcmd:
# opensuse tumbleweed 镜像有 /etc/ssh/sshd_config.d/ 文件夹,没有 /etc/ssh/sshd_config,有/usr/etc/ssh/sshd_config
# opensuse tumbleweed cloud-init 直接创建并写入 /etc/ssh/sshd_config,造成默认配置丢失
# 下面这行删除 clout-init 创建的 sshd_config
- test $(wc -l </etc/ssh/sshd_config) -le 1 && cat /etc/ssh/sshd_config >>/etc/ssh/sshd_config.d/50-cloud-init.conf && rm -f /etc/ssh/sshd_config
- echo "PermitRootLogin yes" >/etc/ssh/sshd_config.d/01-permitrootlogin.conf 2>/dev/null || sed -Ei 's/^#?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
- echo "Port @SSH_PORT@" >/etc/ssh/sshd_config.d/01-change-ssh-port.conf || sed -Ei 's/^#?Port .*/Port @SSH_PORT@/' /etc/ssh/sshd_config
# 已创建的 ssh 连接会沿用旧的配置(未开启密码登录),这时即使输入正确的密码,也会提示 Access Denied
# systemctl restart sshd 只会重启监听进程,不会关闭已创建的连接(子进程)
- pkill sshd || true
# daemon-reload 会刷新 /run/systemd/generator/ssh.socket.d/addresses.conf
- systemctl daemon-reload
- for s in ssh.socket ssh.service sshd.socket sshd.service; do systemctl is-enabled $s 2>/dev/null && systemctl restart $s && break; done
# 删除有密码的行
- sed -i -e '/^[[:space:]]*password:/d' -e '/[[:space:]]*root:/d' /etc/cloud/cloud.cfg.d/99_fallback.cfg
- touch /etc/cloud/cloud-init.disabled
# ubuntu 镜像运行 echo -e '\nDone' ,-e 会被显示出来
# 加 true 因为有的 tty 不可写
- for tty in tty0 ttyS0 ttyAMA0; do [ -c /dev/$tty ] && printf '\n%s\n' 'reinstall done' >/dev/$tty || true; done
+164
View File
@@ -0,0 +1,164 @@
# shellcheck disable=SC2148
# 设置
keyboard --vckeymap=us --xlayouts='us'
lang en_US.UTF-8
timezone Asia/Shanghai --utc
rootpw --plaintext 123@@@
text
reboot
%include /tmp/include-url-command
# 分区
%include /tmp/include-disk-only-use
%include /tmp/include-bootloader
clearpart --all --initlabel
reqpart # 如果需要,自动创建 efi 或 biosboot 分区
part / --fstype=xfs --grow
# 软件
%packages --ignoremissing # el9 minimal.iso fedora Server repo/iso 没有 tuned
@^Minimal Install
%include /tmp/include-packages-for-resize
%include /tmp/exclude-packages-for-vm
%end
# 禁用防火墙
# firewall --disabled
# 禁用 selinux
selinux --disabled
# 禁用 kdump
%addon com_redhat_kdump --disable
%end
##############################################
%pre
distro=$(awk -F: '{ print $3 }' </etc/system-release-cpe)
releasever=$(awk -F: '{ print $5 }' </etc/system-release-cpe)
# 重新整理 extra,grub把两侧的引号吃掉了,eval出错,要重新添加引号
# 提取 extra_confhome extra_mirrorlist extra_main_disk
prefix=extra
for var in $(grep -o "\b${prefix}_[^ ]*" /proc/cmdline | xargs); do
eval "$(echo "$var" | sed -E "s/${prefix}_([^=]*)=(.*)/\1='\2'/")"
done
# centos7 证书链未更新,需要 --no-check-certificate
# 只使用主硬盘
include=/tmp/include-disk-only-use
xda=$(wget --no-check-certificate --tries=5 "$confhome/get-xda.sh" -O- | sh -s)
echo "ignoredisk --only-use=$xda" >$include
# 设置 tty
include=/tmp/include-bootloader
# shellcheck disable=SC2154
console_cmdline=$(wget --no-check-certificate --tries=5 "$confhome/ttys.sh" -O- | sh -s console=)
echo "bootloader --append=\"$console_cmdline\"" >$include
# 有 installer 分区,表示用了两步安装
include=/tmp/include-packages-for-resize
touch $include
if [ -e /dev/disk/by-label/installer ]; then
# 1g内存下,安装器默认开启了zram ,但安装f38还是不够内存
# 具体表现为不断重启安装界面,所以还要开启swap
ram_size=$(lsmem -b 2>/dev/null | grep 'Total online memory:' | awk '{ print $NF/1024/1024 }')
if [ -z "$ram_size" ] || [ "$ram_size" -le 1024 ]; then
mount /dev/disk/by-label/installer /run/install/repo -o remount,rw
swapfile=/run/install/repo/swapfile
if command -v fallocate; then
fallocate -l 1G $swapfile
else
dd if=/dev/zero of=$swapfile bs=1M count=1024
fi
chmod 0600 $swapfile
mkswap $swapfile
swapon $swapfile
fi
# feroda 默认不包含 cronie
echo cronie >>$include
# el7 的parted不支持在线扩容,要用 growpart 和 gdisk 处理 gpt 分区
if [ "$releasever" = "7" ]; then
echo cloud-utils-growpart >>$include
echo gdisk >>$include
fi
fi
# 排除虚拟机用不上的组件
include=/tmp/exclude-packages-for-vm
touch $include
if systemd-detect-virt -v; then
cat <<EOF >$include
# 不删除usb相关的包 因为甲骨文云有usb设备 作用未知
# -usb_modeswitch
# -usbutils
# 无线
-iw
-crda
-rfkill
-iwl*-firmware
# 其他
-irqbalance # 多核+直通设备可能有用?
-microcode_ctl
-smartmontools
# 各种固件
-aic94xx-firmware
-alsa-firmware
-ivtv-firmware
# -linux-firmware # 去除后安装centos 8会报错
# fedora 特有固件
-amd-gpu-firmware
-atheros-firmware
-brcmfmac-firmware
-intel-gpu-firmware
-mt7xxx-firmware
-nvidia-gpu-firmware
-realtek-firmware
EOF
fi
# 设置安装源
include=/tmp/include-url-command
# shellcheck disable=SC2154
if [ "$localtest" = 1 ]; then
echo "url --url=$confhome/$releasever/" >$include
# echo cdrom >$include
else
echo "url --mirrorlist=$mirrorlist" >$include
# 对于el7/fedora, 添加了 updates repo 才会安装最新的包
if [ "$releasever" = "7" ] || [ "$distro" = "fedoraproject" ]; then
echo "repo --name=updates" >>$include
fi
fi
%end
##############################################
%post
# el9/fedora的sshd默认不允许root密码登录,需手动开启
# rootpw --allow-ssh 9.1 以上才支持
distro=$(awk -F: '{ print $3 }' </etc/system-release-cpe)
releasever=$(awk -F: '{ print $5 }' </etc/system-release-cpe)
if [ "$releasever" = "9" ] || [ "$distro" = "fedoraproject" ]; then
echo "PermitRootLogin yes" >/etc/ssh/sshd_config.d/01-permitrootlogin.conf
fi
# 分步安装的系统,要将最后一个分区(installer)合并到系统分区
if [ -e /dev/disk/by-label/installer ]; then
# 提取 extra_localtest extra_confhome extra_mirrorlist
prefix=extra
for var in $(grep -o "\b${prefix}_[^ ]*" /proc/cmdline | xargs); do
eval "$(echo "$var" | sed -E "s/${prefix}_([^=]*)=(.*)/\1='\2'/")"
done
cd /
curl -O "$confhome/deprecated/resize.sh"
echo '@reboot root bash /resize.sh' >/etc/cron.d/resize
fi
%end
+60
View File
@@ -0,0 +1,60 @@
#!/bin/bash
PATH="/usr/sbin:/usr/bin"
update_part() {
partx -u "$1"
udevadm trigger
udevadm settle
}
# el 自带 fdisk parted (el7的part不支持在线扩容)
# ubuntu 自带 fdisk growpart
# 删除分区用
# el/ubuntu fdisk
# 扩容分区用
# el7 grownparted 额外安装
# el8/9/fedora parted
# ubuntu grownpart
# 找出主硬盘
root_drive=$(mount | awk '$3=="/" {print $1}')
xda=$(lsblk -r --inverse "$root_drive" | grep -w disk | awk '{print $1}')
# 删除 installer 分区
installer_num=$(readlink -f /dev/disk/by-label/installer | grep -o '[0-9]*$')
if [ -n "$installer_num" ]; then
# 要添加 LC_NUMERIC 或者将%转义成\%才能在cron里正确运行
# locale -a 不一定有"en_US.UTF-8",但肯定有"C.UTF-8"
LC_NUMERIC="C.UTF-8"
printf "d\n%s\nw" "$installer_num" | fdisk "/dev/$xda"
update_part "/dev/$xda"
fi
# 找出现在的最后一个分区,也就是系统分区
# el7 的 lsblk 没有 --sort,所以用其他方法
# shellcheck disable=2012
part_num=$(ls -1v "/dev/$xda"* | tail -1 | grep -o '[0-9]*$')
part_fstype=$(lsblk -no FSTYPE "/dev/$xda"*"$part_num")
# 扩容分区
# ubuntu 和 el7 用 growpart,其他用 parted
# el7 不能用parted在线扩容,而fdisk扩容会改变 PARTUUID,所以用 growpart
if grep -E -i 'centos:7|ubuntu' /etc/os-release; then
growpart "/dev/$xda" "$part_num"
else
printf 'yes\n100%%' | parted "/dev/$xda" resizepart "$part_num" ---pretend-input-tty
fi
update_part "/dev/$xda"
# 扩容最后一个分区的文件系统
case $part_fstype in
xfs) xfs_growfs / ;;
ext*) resize2fs "/dev/$xda"*"$part_num" ;;
btrfs) btrfs filesystem resize max / ;;
esac
update_part "/dev/$xda"
# 删除脚本自身
rm -f /resize.sh /etc/cron.d/resize
+127
View File
@@ -0,0 +1,127 @@
#!/bin/bash
sed -i -E '/^\.{3}$/d' /autoinstall.yaml
echo 'storage:' >>/autoinstall.yaml
# 禁用 swap
cat <<EOF >>/autoinstall.yaml
swap:
size: 0
EOF
# 是用 size 寻找分区,number 没什么用
# https://curtin.readthedocs.io/en/latest/topics/storage.html
size_os=$(lsblk -bn -o SIZE /dev/disk/by-label/os)
# shellcheck disable=SC2154
if parted "/dev/$xda" print | grep '^Partition Table' | grep gpt; then
# efi
if [ -e /dev/disk/by-label/efi ]; then
size_efi=$(lsblk -bn -o SIZE /dev/disk/by-label/efi)
cat <<EOF >>/autoinstall.yaml
config:
# disk
- ptable: gpt
path: /dev/$xda
preserve: true
type: disk
id: disk-xda
# efi 分区
- device: disk-xda
size: $size_efi
number: 1
preserve: true
grub_device: true
type: partition
id: partition-efi
- fstype: fat32
volume: partition-efi
type: format
id: format-efi
# os 分区
- device: disk-xda
size: $size_os
number: 2
preserve: true
type: partition
id: partition-os
- fstype: ext4
volume: partition-os
type: format
id: format-os
# mount
- path: /
device: format-os
type: mount
id: mount-os
- path: /boot/efi
device: format-efi
type: mount
id: mount-efi
EOF
else
# bios > 2t
size_biosboot=$(parted "/dev/$xda" unit b print | grep bios_grub | awk '{print $4}' | sed 's/B$//')
cat <<EOF >>/autoinstall.yaml
config:
# disk
- ptable: gpt
path: /dev/$xda
preserve: true
grub_device: true
type: disk
id: disk-xda
# biosboot 分区
- device: disk-xda
size: $size_biosboot
number: 1
preserve: true
type: partition
id: partition-biosboot
# os 分区
- device: disk-xda
size: $size_os
number: 2
preserve: true
type: partition
id: partition-os
- fstype: ext4
volume: partition-os
type: format
id: format-os
# mount
- path: /
device: format-os
type: mount
id: mount-os
EOF
fi
else
# bios
cat <<EOF >>/autoinstall.yaml
config:
# disk
- ptable: msdos
path: /dev/$xda
preserve: true
grub_device: true
type: disk
id: disk-xda
# os 分区
- device: disk-xda
size: $size_os
number: 1
preserve: true
type: partition
id: partition-os
- fstype: ext4
volume: partition-os
type: format
id: format-os
# mount
- path: /
device: format-os
type: mount
id: mount-os
EOF
fi
echo ... >>/autoinstall.yaml
+97
View File
@@ -0,0 +1,97 @@
#cloud-config
# 顺序 early-commands > 安装系统 > late-commands > 重启进入系统 > cloud-init: runcmd > cloud-init: 其他
autoinstall:
version: 1
apt:
fallback: offline-install
source:
id: "@SOURCE_ID@"
kernel:
package: linux-generic
timezone: Asia/Shanghai
ssh:
allow-pw: true
authorized-keys: []
install-server: true
early-commands:
- |
# 解决 20.04 不能识别硬盘
# https://askubuntu.com/questions/1302392/ubuntu-server-20-04-setup-stuck-at-block-probing-did-not-discover-any-disks
mount | grep /isodevice && { losetup -d /dev/loop0; umount -l /isodevice; } || true
# 提取 extra_confhome extra_kernel
prefix=extra
for var in $(grep -o "\b${prefix}_[^ ]*" /proc/cmdline | xargs); do
eval "$(echo $var | sed -E "s/${prefix}_([^=]*)=(.*)/\1='\2'/")"
done
# 生成分区信息
xda=$(curl -L "$confhome/get-xda.sh" | sh -s)
export xda
curl -L "$confhome/deprecated/ubuntu-storage-early.sh" | sh -s
# 要安装的版本
# 有的镜像只有一个版本,没有 install-sources.yaml
# 因此提取不到 $source_id,此时 $source_id 参数为空
if [ -n "$source_id" ]; then
sed -i "s/@SOURCE_ID@/$source_id/" /autoinstall.yaml
else
sed -i "/@SOURCE_ID@/d" /autoinstall.yaml
fi
# 内核风味
# https://bugs.launchpad.net/subiquity/+bug/1989353
sed -i "s/generic/$kernel/" /run/kernel-meta-package
sed -i "/package:/s/generic/$kernel/" /autoinstall.yaml
# 跳过最后的更新
cp /usr/sbin/chroot /usr/sbin/chroot.bin
cat >/usr/sbin/chroot <<EOF
#!/bin/sh
[ "\$2" = "unattended-upgrades" ] || /usr/sbin/chroot.bin "\$@"
EOF
# 禁用 DNS 强制离线安装内核和跳过最后的更新
# 但安装器会配置时区和写入最近的mirror到/etc/apt/sources.list 所以要提前解析
# dig会显示cname结果,cname会以.结尾,grep -v '\.$' 表示去除 cname 结果
# echo $(dig +short geoip.ubuntu.com | grep -v '\.$' | head -1) geoip.ubuntu.com >>/etc/hosts
# sed -i -E 's/(^nameserver )/#\1/' /etc/resolv.conf
late-commands:
- |
# root ssh 登录
echo "PermitRootLogin yes" >/target/etc/ssh/sshd_config.d/01-permitrootlogin.conf
# 还原 DNS
# sed -i -E 's/^#(nameserver )/\1/' /etc/resolv.conf
# 提取 extra_confhome
prefix=extra
for var in $(grep -o "\b${prefix}_[^ ]*" /proc/cmdline | xargs); do
eval "$(echo $var | sed -E "s/${prefix}_([^=]*)=(.*)/\1='\2'/")"
done
# 下载合并分区脚本
cd /target
curl -LO $confhome/deprecated/resize.sh
# 升级 cloud-init
# curtin in-target --target=/target -- apt update
# curtin in-target --target=/target -- apt install --only-upgrade cloud-init
user-data:
runcmd:
- |
# 合并分区
bash /resize.sh
disable_root: false
users:
- name: root
lock_passwd: false
chpasswd:
expire: false
# 20.04 arm 需要
list: |
root:123@@@
users:
- name: root
password: 123@@@
type: text