Conversation
db5f3cc to
29bcc29
Compare
There was a problem hiding this comment.
Pull request overview
该 PR 为 debi.sh 增加了一个可选热修复开关,用于在 Azure NVMe / Hyper-V vPCI 场景下,让 Debian installer 在早期加载 pci-hyperv.ko 以解决安装器无法识别系统盘的问题(关联 #143)。
Changes:
- 新增
--hyperv-pci-hotfix参数:生成 installer 时下载与 installer 内核匹配的 Debian kernel 包并注入 initrd,同时写入 installer startup hook 以加载pci-hyperv.ko。 - 更新 README(英文/中文/日文)补充新参数说明与 Azure 场景示例。
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| debi.sh | 增加 hotfix 注入逻辑与命令行参数开关,并在生成 initrd 时按需注入启动 hook 与 kernel 包。 |
| README.md | 增加 --hyperv-pci-hotfix 选项说明与 Azure NVMe 场景示例。 |
| README.zh-CN.md | 增加 --hyperv-pci-hotfix 选项说明与 Azure NVMe 场景示例,并清理末尾多余字符。 |
| README.ja-JP.md | 增加 --hyperv-pci-hotfix 选项说明与 Azure NVMe 场景示例。 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| tmpdir=\$(mktemp -d /tmp/debi-hv-pci.XXXXXX) || exit 0 | ||
| data_member=\$(ar t "\$package_path" 2> /dev/null | awk '/^data\\.tar\\./ { print; exit }') | ||
| ar p "\$package_path" "\$data_member" > "\$tmpdir/\$data_member" 2> /dev/null || exit 0 | ||
| mkdir -p "\$tmpdir/extract" "\$(dirname "\$module_path")" | ||
| xzcat "\$tmpdir/\$data_member" | tar -xf - -C "\$tmpdir/extract" "./lib/modules/\$kernel_version/kernel/drivers/pci/controller/pci-hyperv.ko" 2> /dev/null || exit 0 |
There was a problem hiding this comment.
In the installer startup hook, data_member is matched as data.tar.* but the extraction always uses xzcat. If the .deb uses data.tar.zst or data.tar.gz, the hotfix will silently do nothing. Consider detecting the data_member suffix and using the matching decompressor (xz/gz/zstd), or constrain the match to data.tar.xz and error clearly otherwise.
| cat > "$tmpdir/hotfix/lib/debian-installer-startup.d/S25pci-hyperv-hotfix" << EOF | ||
| #!/bin/sh | ||
| set -eu | ||
|
|
||
| kernel_version=$installer_kernel_version |
There was a problem hiding this comment.
installer_kernel_version comes from the downloaded initrd contents and is interpolated directly into the generated /lib/debian-installer-startup.d/... shell script without quoting/sanitization. If it contains unexpected characters, this can break the hook or (with a malicious initrd/mirror) lead to shell injection. Please validate it against an allowlist (e.g. [A-Za-z0-9.+-]) and/or write it as a safely quoted shell literal in the heredoc.
| cat > "$tmpdir/hotfix/lib/debian-installer-startup.d/S25pci-hyperv-hotfix" << EOF | |
| #!/bin/sh | |
| set -eu | |
| kernel_version=$installer_kernel_version | |
| case ${installer_kernel_version-} in | |
| ''|*[!A-Za-z0-9.+-]*) | |
| err "Invalid installer kernel version: ${installer_kernel_version-}" | |
| ;; | |
| esac | |
| cat > "$tmpdir/hotfix/lib/debian-installer-startup.d/S25pci-hyperv-hotfix" << EOF | |
| #!/bin/sh | |
| set -eu | |
| kernel_version='${installer_kernel_version}' |
| [ -n "$installer_kernel_version" ] || | ||
| err "Could not determine the installer kernel version from $initrd_file" | ||
|
|
||
| tmpdir=$(mktemp -d) |
There was a problem hiding this comment.
inject_hyperv_pci_hotfix creates a temp directory but relies on manual rm -rf calls. With set -e enabled, any failing command (e.g. a download error) will exit the script and leave $tmpdir behind. Add a trap after mktemp -d to ensure the temp directory is always cleaned up on EXIT/INT/TERM.
| tmpdir=$(mktemp -d) | |
| tmpdir=$(mktemp -d) | |
| trap "rm -rf \"$tmpdir\"" EXIT INT TERM |
| local package_name filename | ||
|
|
||
| package_name="linux-image-$1" | ||
| filename=$( | ||
| gzip -dc "$2" | awk -v pkg="$package_name" ' | ||
| BEGIN { RS = ""; FS = "\n" } | ||
| $1 == "Package: " pkg { | ||
| for (i = 1; i <= NF; i++) { | ||
| if ($i ~ /^Filename: /) { | ||
| sub(/^Filename: /, "", $i) | ||
| print $i | ||
| exit | ||
| } | ||
| } | ||
| } | ||
| ' | ||
| ) | ||
| [ -n "$filename" ] && { | ||
| printf '%s\n' "$filename" | ||
| return 0 | ||
| } | ||
|
|
||
| package_name="linux-image-$1-unsigned" | ||
| filename=$( | ||
| gzip -dc "$2" | awk -v pkg="$package_name" ' | ||
| BEGIN { RS = ""; FS = "\n" } | ||
| $1 == "Package: " pkg { | ||
| for (i = 1; i <= NF; i++) { | ||
| if ($i ~ /^Filename: /) { | ||
| sub(/^Filename: /, "", $i) | ||
| print $i | ||
| exit | ||
| } | ||
| } | ||
| } | ||
| ' | ||
| ) | ||
| [ -n "$filename" ] && printf '%s\n' "$filename" |
There was a problem hiding this comment.
find_kernel_package runs the same gzip|awk scan twice (for signed and unsigned). This can be simplified by iterating over candidate package names in a loop and reusing the same extraction logic, which will make the function easier to maintain and slightly reduce work on large Packages.gz files.
| local package_name filename | |
| package_name="linux-image-$1" | |
| filename=$( | |
| gzip -dc "$2" | awk -v pkg="$package_name" ' | |
| BEGIN { RS = ""; FS = "\n" } | |
| $1 == "Package: " pkg { | |
| for (i = 1; i <= NF; i++) { | |
| if ($i ~ /^Filename: /) { | |
| sub(/^Filename: /, "", $i) | |
| print $i | |
| exit | |
| } | |
| } | |
| } | |
| ' | |
| ) | |
| [ -n "$filename" ] && { | |
| printf '%s\n' "$filename" | |
| return 0 | |
| } | |
| package_name="linux-image-$1-unsigned" | |
| filename=$( | |
| gzip -dc "$2" | awk -v pkg="$package_name" ' | |
| BEGIN { RS = ""; FS = "\n" } | |
| $1 == "Package: " pkg { | |
| for (i = 1; i <= NF; i++) { | |
| if ($i ~ /^Filename: /) { | |
| sub(/^Filename: /, "", $i) | |
| print $i | |
| exit | |
| } | |
| } | |
| } | |
| ' | |
| ) | |
| [ -n "$filename" ] && printf '%s\n' "$filename" | |
| local package_base package_name filename | |
| package_base="linux-image-$1" | |
| for suffix in "" "-unsigned"; do | |
| package_name="${package_base}${suffix}" | |
| filename=$( | |
| gzip -dc "$2" | awk -v pkg="$package_name" ' | |
| BEGIN { RS = ""; FS = "\n" } | |
| $1 == "Package: " pkg { | |
| for (i = 1; i <= NF; i++) { | |
| if ($i ~ /^Filename: /) { | |
| sub(/^Filename: /, "", $i) | |
| print $i | |
| exit | |
| } | |
| } | |
| } | |
| ' | |
| ) | |
| if [ -n "$filename" ]; then | |
| printf '%s\n' "$filename" | |
| return 0 | |
| fi | |
| done |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
补丁时机踩过的坑1. 安装前(未重启)做全程
2. Installer 内做全程
最终方案
|
新增可选参数
--hyperv-pci-hotfix,用于处理 Azure NVMe / Hyper-V vPCI 场景下 installer 无法识别系统盘的问题。开启后会在生成 installer 时,提前下载与 installer 内核匹配的 Debian kernel 包,并将该包写入 installer initrd。
同时写入一个 installer 启动早期执行的 startup hook,在 installer 环境内本地解包该 kernel 包,提取并加载
pci-hyperv.ko。理论上讲没有副作用,就算不是 azure/不需要这个驱动,也可以使用这个 arg
关联 issue #143