-
创建者:
虚拟的现实,上次更新时间:6月 19, 2025 需要 5 分钟阅读时间
简介
LFS 项目不用太多介绍,前面已经有很多的内容描述了。我基于前面的内容考虑实现一个简化版本的支持 docker 的 LFS 环境。从前面实现的 LFS 项目来看需要解决以下几个问题
- 系统服务管理需要与时俱进采用 systemd 的管理方式而不是传统的 Sysvint 的模式
- 系统的内核需要支持容器环境
- 容器服务同时还依赖 git 和 iptables 组件
容器环境要求
官网上有专门的二进制安装方法,安装步骤很简洁,就是下载解压即可使用,但是对系统的依赖说法比较简洁
- A 64-bit installation 64位操作系统(这个都满足)
- Version 3.10 or higher of the Linux kernel. (3.1版本以上的内核,缺乏细致的内核配置要求说明)
- iptables version 1.4 or higher (iptables 版本 1.4 以上,但是该组件相关的依赖非常多,官网没有更详细的说明)
- git version 1.7 or higher (git 版本容易满足)
- A ps executable, usually provided by procps or a similar package. (ps 工具)
- XZ Utils 4.9 or higher (xz 压缩工具及对应的版本)
- A properly mounted cgroupfs hierarchy; a single, all-encompassing cgroup mount point is not sufficient. (cggoup 相关的支持)
最麻烦的其实时内核编译所需的组件配置,因为内核编译相关的组件太多了,容器环境涉及存储、网络、cggroup、服务等多方面的内容。
LFS 相关
LFS 直接参照之前的步骤,除了在创建系统文件(passwd 和 group )及 systemd 组件及后续配置有不同外,其他的步骤可以沿用。
调整的部分主要包括
- /etc/passwd
- /etc/group
- 网络配置文件
- systemd 组件
- 内核配置
详细的步骤 参照 LFS systemd 项目(https://www.linuxfromscratch.org/lfs/view/stable-systemd/)
构建基础环境
1、参照 4014-LFS 自定义 Linux(上)的描述直至完成【3. 交叉编译临时工具】
2、在【4. 进入 Chroot 并构建其他临时工具】步骤中调整【4.4. 创建目录和相关文件】的配置如下
mkdir -pv /{boot,home,mnt,opt,srv} mkdir -pv /etc/{opt,sysconfig} mkdir -pv /lib/firmware mkdir -pv /media/{floppy,cdrom} mkdir -pv /usr/{,local/}{include,src} mkdir -pv /usr/lib/locale mkdir -pv /usr/local/{bin,lib,sbin} mkdir -pv /usr/{,local/}share/{color,dict,doc,info,locale,man} mkdir -pv /usr/{,local/}share/{misc,terminfo,zoneinfo} mkdir -pv /usr/{,local/}share/man/man{1..8} mkdir -pv /var/{cache,local,log,mail,opt,spool} mkdir -pv /var/lib/{color,misc,locate} ln -sfv /run /var/run ln -sfv /run/lock /var/lock install -dv -m 0750 /root install -dv -m 1777 /tmp /var/tmp ln -sv /proc/self/mounts /etc/mtab cat > /etc/hosts << EOF 127.0.0.1 localhost $(hostname) ::1 localhost EOF cat > /etc/passwd << "EOF" root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/dev/null:/usr/bin/false daemon:x:6:6:Daemon User:/dev/null:/usr/bin/false messagebus:x:18:18:D-Bus Message Daemon User:/run/dbus:/usr/bin/false uuidd:x:80:80:UUID Generation Daemon User:/dev/null:/usr/bin/false nobody:x:65534:65534:Unprivileged User:/dev/null:/usr/bin/false systemd-journal-gateway:x:73:73:systemd Journal Gateway:/:/usr/bin/false systemd-journal-remote:x:74:74:systemd Journal Remote:/:/usr/bin/false systemd-journal-upload:x:75:75:systemd Journal Upload:/:/usr/bin/false systemd-network:x:76:76:systemd Network Management:/:/usr/bin/false systemd-resolve:x:77:77:systemd Resolver:/:/usr/bin/false systemd-timesync:x:78:78:systemd Time Synchronization:/:/usr/bin/false systemd-coredump:x:79:79:systemd Core Dumper:/:/usr/bin/false systemd-oom:x:81:81:systemd Out Of Memory Daemon:/:/usr/bin/false EOF cat > /etc/group << "EOF" root:x:0: bin:x:1:daemon sys:x:2: kmem:x:3: tape:x:4: tty:x:5: daemon:x:6: floppy:x:7: disk:x:8: lp:x:9: dialout:x:10: audio:x:11: video:x:12: utmp:x:13: cdrom:x:15: adm:x:16: messagebus:x:18: input:x:24: mail:x:34: kvm:x:61: uuidd:x:80: wheel:x:97: users:x:999: nogroup:x:65534: systemd-journal-gateway:x:73: systemd-journal-remote:x:74: systemd-journal-upload:x:75: systemd-network:x:76: systemd-resolve:x:77: systemd-timesync:x:78: systemd-coredump:x:79: systemd-oom:x:81: EOF echo "tester:x:101:101::/home/tester:/bin/bash" >> /etc/passwd echo "tester:x:101:" >> /etc/group install -o tester -d /home/tester exec /usr/bin/bash --login touch /var/log/{btmp,lastlog,faillog,wtmp} chgrp -v utmp /var/log/lastlog chmod -v 664 /var/log/lastlog chmod -v 600 /var/log/btmp
可以看到和之前的版本相比主要是增加了【systemd-journal-gateway、systemd-journal-remote、systemd-journal-upload、systemd-network、systemd-resolve、systemd-timesync、systemd-coredump、
systemd-oom】这些用户和组的信息
如果没有这些用户和组,后面操作系统在启动时相关的服务都将无法正常启动。例如 “systemd-oomd failed to determine user credentials”类似的错误
3、参照【4. 进入 Chroot 并构建其他临时工具】完成该部分的其它步骤
构建 LFS 系统
参照【5. 构建 LFS 系统】完成直到【5.73. Systemd-257.3 中的 Udev】,该步骤对应 LFS 官网项目中的 (8.76. Systemd-257.3 https://www.linuxfromscratch.org/lfs/view/stable-systemd/chapter08/systemd.html)这节
Systemd-257.3
tar xvf systemd-257.3.tar.gz cd systemd-257.3 sed -e 's/GROUP="render"/GROUP="video"/' \ -e 's/GROUP="sgx", //' \ -i rules.d/50-udev-default.rules.in mkdir -p build cd build meson setup .. \ --prefix=/usr \ --buildtype=release \ -D default-dnssec=no \ -D firstboot=false \ -D install-tests=false \ -D ldconfig=false \ -D sysusers=false \ -D rpmmacrosdir=no \ -D homed=disabled \ -D userdb=false \ -D man=disabled \ -D mode=release \ -D pamconfdir=no \ -D dev-kvm-mode=0660 \ -D nobody-group=nogroup \ -D sysupdate=disabled \ -D ukify=disabled \ -D docdir=/usr/share/doc/systemd-257.3 ninja ninja install systemd-machine-id-setup systemctl preset-all
D-Bus-1.16.0
tar xvf dbus-1.16.0.tar.xz cd dbus-1.16.0 mkdir build cd build meson setup --prefix=/usr --buildtype=release --wrap-mode=nofallback .. ninja ninja install ln -sfv /etc/machine-id /var/lib/dbus
Man-DB-2.13.0
tar xvf man-db-2.13.0.tar.xz cd man-db-2.13.0 ./configure --prefix=/usr \ --docdir=/usr/share/doc/man-db-2.13.0 \ --sysconfdir=/etc \ --disable-setuid \ --enable-cache-owner=bin \ --with-browser=/usr/bin/lynx \ --with-vgrind=/usr/bin/vgrind \ --with-grap=/usr/bin/grap make make install
Procps-ng-4.0.5
tar xvf procps-ng-4.0.5.tar.xz cd procps-ng-4.0.5 ./configure --prefix=/usr \ --docdir=/usr/share/doc/procps-ng-4.0.5 \ --disable-static \ --disable-kill \ --enable-watch8bit \ --with-systemd make make install
Util-linux-2.40.4
tar xvf util-linux-2.40.4.tar.xz cd util-linux-2.40.4 ./configure --bindir=/usr/bin \ --libdir=/usr/lib \ --runstatedir=/run \ --sbindir=/usr/sbin \ --disable-chfn-chsh \ --disable-login \ --disable-nologin \ --disable-su \ --disable-setpriv \ --disable-runuser \ --disable-pylibmount \ --disable-liblastlog2 \ --disable-static \ --without-python \ --without-systemd \ --without-systemdsystemunitdir \ ADJTIME_PATH=/var/lib/hwclock/adjtime \ --docdir=/usr/share/doc/util-linux-2.40.4 make make install
E2fsprogs-1.47.2
tar xvf e2fsprogs-1.47.2.tar.gz cd e2fsprogs-1.47.2 mkdir -v build cd build ../configure --prefix=/usr \ --sysconfdir=/etc \ --enable-elf-shlibs \ --disable-libblkid \ --disable-libuuid \ --disable-uuidd \ --disable-fsck make make install rm -fv /usr/lib/{libcom_err,libe2p,libext2fs,libss}.a gunzip -v /usr/share/info/libext2fs.info.gz install-info --dir-file=/usr/share/info/dir /usr/share/info/libext2fs.info sed 's/metadata_csum_seed,//' -i /etc/mke2fs.conf
移除调试符号(可选)
save_usrlib="$(cd /usr/lib; ls ld-linux*[^g]) libc.so.6 libthread_db.so.1 libquadmath.so.0.0.0 libstdc++.so.6.0.33 libitm.so.1.0.0 libatomic.so.1.2.0" cd /usr/lib for LIB in $save_usrlib; do objcopy --only-keep-debug --compress-debug-sections=zlib $LIB $LIB.dbg cp $LIB /tmp/$LIB strip --strip-unneeded /tmp/$LIB objcopy --add-gnu-debuglink=$LIB.dbg /tmp/$LIB install -vm755 /tmp/$LIB /usr/lib rm /tmp/$LIB done online_usrbin="bash find strip" online_usrlib="libbfd-2.44.so libsframe.so.1.0.0 libhistory.so.8.2 libncursesw.so.6.5 libm.so.6 libreadline.so.8.2 libz.so.1.3.1 libzstd.so.1.5.7 $(cd /usr/lib; find libnss*.so* -type f)" for BIN in $online_usrbin; do cp /usr/bin/$BIN /tmp/$BIN strip --strip-unneeded /tmp/$BIN install -vm755 /tmp/$BIN /usr/bin rm /tmp/$BIN done for LIB in $online_usrlib; do cp /usr/lib/$LIB /tmp/$LIB strip --strip-unneeded /tmp/$LIB install -vm755 /tmp/$LIB /usr/lib rm /tmp/$LIB done for i in $(find /usr/lib -type f -name \*.so* ! -name \*dbg) \ $(find /usr/lib -type f -name \*.a) \ $(find /usr/{bin,sbin,libexec} -type f); do case "$online_usrbin $online_usrlib $save_usrlib" in *$(basename $i)* ) ;; * ) strip --strip-unneeded $i ;; esac done unset BIN LIB save_usrlib online_usrbin online_usrlib rm -rf /tmp/{*,.*} find /usr/lib /usr/libexec -name \*.la -delete find /usr -depth -name $(uname -m)-lfs-linux-gnu\* | xargs rm -rf
系统配置
系统配置的步骤也可以对照【1. 系统配置】的步骤。但是 systemd 版本和之前的存在差异,特别时启动脚本和网络配置。
通用网络配置
默认情况下网络的接口名称由 udev 进程自动管理和生成,udev 进程包含在 【3.1. Systemd-257.3】中。由于当前是 chroot 环境,系统无法正常生成网卡名称
如果需要自定义网卡名称有三种方法:
- 屏蔽 udev 的默认规则
ln -s /dev/null /etc/systemd/network/99-default.link
- 创建自定义的命名方案,例如将网卡命名为 ether0
cat > /etc/systemd/network/10-ether0.link << "EOF" [Match] # Change the MAC address as appropriate for your network device MACAddress=12:34:45:78:90:AB [Link] Name=ether0 EOF
- 在 /boot/grub/grub.cfg 文件中的内核选项中添加 net.ifnames=0 参数
配置静态 IP(实际例子)
cat > /etc/systemd/network/10-eth-static.network << "EOF" [Match] Name=ether0 [Network] Address=192.168.77.196/24 Gateway=192.168.77.1 DNS=192.168.77.4 Domains=lfs.local EOF
配置 DHCP
cat > /etc/systemd/network/10-eth-dhcp.network << "EOF" [Match] Name=<network-device-name> [Network] DHCP=ipv4 [DHCPv4] UseDomains=true EOF
主机名称和域名解析配置
cat > /etc/resolv.conf << "EOF" # Begin /etc/resolv.conf domain lfs.local nameserver 10.0.2.3 nameserver 223.5.5.5 # End /etc/resolv.conf EOF echo "LFS" > /etc/hostname cat > /etc/hosts << "EOF" # Begin /etc/hosts 127.0.0.1 localhost.localdomain localhost 127.0.1.1 <FQDN> <HOSTNAME> <192.168.1.2> <FQDN> <HOSTNAME> [alias1] [alias2 ...] ::1 localhost ip6-localhost ip6-loopback ff02::1 ip6-allnodes ff02::2 ip6-allrouters # End /etc/hosts EOF cat > /etc/sysconfig/clock << "EOF" # Begin /etc/sysconfig/clock UTC=1 # Set this to any options you might need to give to hwclock, # such as machine hardware clock type for Alphas. CLOCKPARAMS= # End /etc/sysconfig/clock EOF cat > /etc/profile << "EOF" # Begin /etc/profile for i in $(locale); do unset ${i%=*} done if [[ "$TERM" = linux ]]; then export LANG=C.UTF-8 else export LANG=en_US.UTF-8 fi # End /etc/profile EOF
创建 /etc/inputrc 文件
cat > /etc/inputrc << "EOF" # Begin /etc/inputrc # Modified by Chris Lynn <roryo@roryo.dynup.net> # Allow the command prompt to wrap to the next line set horizontal-scroll-mode Off # Enable 8-bit input set meta-flag On set input-meta On # Turns off 8th bit stripping set convert-meta Off # Keep the 8th bit for display set output-meta On # none, visible or audible set bell-style none # All of the following map the escape sequence of the value # contained in the 1st argument to the readline specific functions "\eOd": backward-word "\eOc": forward-word # for linux console "\e[1~": beginning-of-line "\e[4~": end-of-line "\e[5~": beginning-of-history "\e[6~": end-of-history "\e[3~": delete-char "\e[2~": quoted-insert # for xterm "\eOH": beginning-of-line "\eOF": end-of-line # for Konsole "\e[H": beginning-of-line "\e[F": end-of-line # End /etc/inputrc EOF
创建 /etc/shells 文件
cat > /etc/shells << "EOF" # Begin /etc/shells /bin/sh /bin/bash # End /etc/shells EOF
LFS 系统引导配置
cat > /etc/fstab << "EOF" PARTUUID=2b499aa4-01 / ext4 defaults 1 1 PARTUUID=2b499aa4-02 swap swap pri=1 0 0 proc /proc proc nosuid,noexec,nodev 0 0 sysfs /sys sysfs nosuid,noexec,nodev 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 tmpfs /run tmpfs defaults 0 0 devtmpfs /dev devtmpfs mode=0755,nosuid 0 0 tmpfs /dev/shm tmpfs nosuid,nodev 0 0 cgroup2 /sys/fs/cgroup cgroup2 nosuid,noexec,nodev 0 0 EOF
- 无标签