我在 TS412 (QNAP) 上运行 Debian Bookworm;它将内核和 initrd 存储在闪存中。它总共有 16MB 闪存。因此,即使在调整 MD 分区之后,我能得到的最好的也是 12MB initrd 。我正在使用 xz 压缩。但即便如此,最初的 initrd 也有 12.5MB。我知道常见的解决方法是减少模块,但它们不是真正的问题。
2984 .../usr/lib/modules
6036 .../usr/share
18824 .../usr/lib/arm-linux-gnueabi
在arm-linux-gnueabi中查看它有像libX11这样的东西...这台机器甚至没有控制台(即使获得串行线也很困难)它当然不需要“X”。
因此,我完全删除了很多软件包(apt-get remove ...),实际上比我应该删除的要多。但结果是一个小得多的 initrd(大约 5MB IIRC),它启动和运行得很好。
问题是,如果我 ssh 到盒子上并运行 emacs(1) ,那么将 GUI 版本投影回我的普通桌面(有大量内存和大显示器等)会很好,但这需要安装TS412 上的 X 客户端库。
现在我不明白为什么仅仅因为我安装了带有 X 客户端库的软件包,就需要在 initrd 上保留一个副本,而在启动过程中不需要它们。有没有办法限制其他东西进入 initrd,而不仅仅是模块(这不是罪魁祸首)
我已经尝试过在文档中搜索限制 initrd 的指南。
答案1
可能有一个旨在在启动期间显示图形信息的二进制文件,该二进制文件将拉取它所依赖的库初始化文件系统文件。
大多数架构上都有这样的二进制文件,包括armel
由label.so
plymouth-label
作为插件普利茅斯为了在启动期间有带有文本的图形显示。该插件依赖于各种X11库,用于渲染文本。当这个插件添加到初始化文件系统它还添加了它所依赖的所有库,以便可以在引导阶段使用它。这是由包的依赖项通告的:plymouth-label
取决于libcairo2
它本身依赖于各种 X11 库包,包括libx11-6
提供图书馆libX11.so.6
。
添加的 initramfs 钩子label.so
是/usr/share/initramfs-tools/hooks/plymouth
:
PLUGIN_PATH="$(plymouth --get-splash-plugin-path)" case "${THEME_NAME}" in text|details|tribar) PLUGINS="text.so details.so" ;; *) PLUGINS="text.so details.so label.so" ;; esac [...] for PLUGIN in ${PLUGINS} do if [ -f ${PLUGIN_PATH}/${PLUGIN} ] then copy_exec ${PLUGIN_PATH}/${PLUGIN} else [...]
copy_exec
是一个 shell 函数(由 提供initramfs-tools-core
),除了复制二进制文件之外,它还会在需要时提取依赖项,依赖于ldd
发现需要的内容。
因此,只有在普利茅斯使用非文本设置时才会拉动它......以便显示文本。
由于 QNAP 的主要目的不是视频,因此普利茅斯安装,尤其是应避免使用此插件,避免将 X11 库拉入初始化文件系统文件。
我看不出造成这种行为的任何其他原因。可能有其他类似的包出于类似的原因导致此行为。
答案2
遵循@AB有用回复的逻辑。我敲出了一对快速而肮脏的脚本来帮助跟踪依赖树。 (AB答案仍然是具体问题的答案)
graeme@qnap412u:/tmp/myinitrd$ xzcat /boot/initrd.img-6.1.0-13-marvell | cpio -i
34382 blocks
graeme@qnap412u:/tmp/myinitrd$ ~/bin/genxrefs.sh /tmp/myinitrd/ > /tmp/refs
Doing /tmp/myinitrd/usr/lib/klibc-tUxlTFMpGlp_BpS5UnpMpyc8b3g.so
not a dynamic executable
Doing /tmp/myinitrd/usr/lib/arm-linux-gnueabi/ld-linux.so.3
Doing /tmp/myinitrd/usr/lib/arm-linux-gnueabi/libkmod.so.2.4.0
..elided..
graeme@qnap412u:/tmp/myinitrd$ ~/bin/whoneeds.awk libudev /tmp/refs
libudev.so.1 is used by /tmp/myinitrd/usr/lib/arm-linux-gnueabi/libdevmapper.so.1.02.1
graeme@qnap412u:/tmp/myinitrd$ ~/bin/whoneeds.awk devmapper /tmp/refs
graeme@qnap412u:/tmp/myinitrd$ ~/bin/whoneeds.awk libatomic /tmp/refs
libatomic.so.1 is used by /tmp/myinitrd/usr/lib/arm-linux-gnueabi/libkmod.so.2.4.0
libatomic.so.1 is used by /tmp/myinitrd/usr/lib/arm-linux-gnueabi/libcrypto.so.3
graeme@qnap412u:/tmp/myinitrd$ cat ~/bin/genxrefs.sh
#! /bin/bash -ue
# This will fail if any names uses spaces or commas (at a pinch, we could use TAB)
INITDIR=$1
objs=$(find ${INITDIR} -type f -name '*.so.*' -o -path '*.so')
# This is going to mess up if anybody uses spaces in pathnames
for obj in ${objs}
do
echo "Doing ${obj}" >&2
ldd ${obj} | while read line
do
requires=${line%% =>*}
requires=${requires%% *} # 1st word
requires=$(basename ${requires})
provided=${line#*=>}
# Ugly , we use commas because, for example quoted strings are too hard in awk(1)
echo "${obj},${requires},${provided}"
done
done
graeme@qnap412u:/tmp/myinitrd$ cat ~/bin/whoneeds.awk
#! /usr/bin/awk -f
BEGIN {
# NB this version of awk does not appear to understand FPAT
FS=","
STRING=ARGV[1]
ARGV[1]=""
}
{ if ( index($2, STRING) > 0 )
print $2 " is used by " $1 }