现在开始就要 chroot 了,同时现在开始用户也要从lfs
到root
。
不过这个顺序相比 9.0 差别太大了吧……
那么,现在就su
吧。
记得设置$LFS
:
export LFS=/mnt/lfs
改变 LFS 系统目录的所有者
毕竟一个正常的系统其系统文件所有者不可能是lfs
1 2 3 4
| chown -R root:root $LFS/{usr,lib,var,etc,bin,sbin,tools} case $(uname -m) in x86_64) chown -R root:root $LFS/lib64 ;; esac
|
准备虚拟内核文件系统
首先需要建立 dev,proc,sys,run 目录
mkdir -pv $LFS/{dev,proc,sys,run}
创建初始设备节点
主要是null
和console
1 2
| mknod -m 600 $LFS/dev/console c 5 1 mknod -m 666 $LFS/dev/null c 1 3
|
挂载 /dev
mount -v --bind /dev $LFS/dev
挂载虚拟内核文件系统
1 2 3 4
| mount -v --bind /dev/pts $LFS/dev/pts mount -vt proc proc $LFS/proc mount -vt sysfs sysfs $LFS/sys mount -vt tmpfs tmpfs $LFS/run
|
此外,还要创建一些目录
1 2 3
| if [ -h $LFS/dev/shm ]; then mkdir -pv $LFS/$(readlink $LFS/dev/shm) fi
|
Chroot
1 2 3 4 5 6
| chroot "$LFS" /usr/bin/env -i \ HOME=/root \ TERM="$TERM" \ PS1='(lfs chroot) \u:\w\$ ' \ PATH=/usr/bin:/usr/sbin \ /bin/bash --login +h
|
这时的 bash 会显示 I have no name,因为没有/etc/passwd
,这是正常的,虽然有点丑 :D
退出时进入 Chroot 的操作
如果只是退出而不关机/重启的话,直接运行上面的命令就行,不然就要重新挂载这些文件系统。
不过建议每次 chroot 前都检查一次。
创建目录
现在再创建一些还需要的目录
mkdir -pv /{boot,home,mnt,opt,srv}
其实有一些目录已经创建了,但这里为了防止遗漏手册还是加上了这些目录。
现在创建子目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| mkdir -pv /etc/{opt,sysconfig} mkdir -pv /lib/firmware mkdir -pv /media/{floppy,cdrom} mkdir -pv /usr/{,local/}{include,src} 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
|
以上目录结构全部基于 FHS,但只加了必要的目录。
创建必要的文件和符号链接
先加上从/etc/mtab
到/proc
的符号链接
ln -sv /proc/self/mounts /etc/mtab
然后是创建一个最简单的/etc/hosts
1 2 3 4
| cat > /etc/hosts << EOF 127.0.0.1 localhost $(hostname) ::1 localhost EOF
|
其实这里的$(hostname)
在其他发行版里是需要手动改的
创建/etc/passwd
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| cat > /etc/passwd << "EOF" root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/dev/null:/bin/false daemon:x:6:6:Daemon User:/dev/null:/bin/false messagebus:x:18:18:D-Bus Message Daemon User:/run/dbus:/bin/false systemd-bus-proxy:x:72:72:systemd Bus Proxy:/:/bin/false systemd-journal-gateway:x:73:73:systemd Journal Gateway:/:/bin/false systemd-journal-remote:x:74:74:systemd Journal Remote:/:/bin/false systemd-journal-upload:x:75:75:systemd Journal Upload:/:/bin/false systemd-network:x:76:76:systemd Network Management:/:/bin/false systemd-resolve:x:77:77:systemd Resolver:/:/bin/false systemd-timesync:x:78:78:systemd Time Synchronization:/:/bin/false systemd-coredump:x:79:79:systemd Core Dumper:/:/bin/false uuidd:x:80:80:UUID Generation Daemon User:/dev/null:/bin/false systemd-oom:x:81:81:systemd Out Of Memory Daemon:/:/bin/false nobody:x:99:99:Unprivileged User:/dev/null:/bin/false EOF
|
可以看出这里加上了 systemd 需要的用户。
创建/etc/group
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| 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: usb:x:14: cdrom:x:15: adm:x:16: messagebus:x:18: systemd-journal:x:23: input:x:24: mail:x:34: kvm:x:61: systemd-bus-proxy:x:72: 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: uuidd:x:80: systemd-oom:x:81:81: wheel:x:97: nogroup:x:99: users:x:999: EOF
|
这里用户组的标准可以看作 LFS 自己的标准了,其中用户组可以根据需要自行修改。
现在需要创建一个之后的测试中需要用到的用户,不过是临时的,最后会删除。
1 2 3
| echo "tester:x:101:101::/home/tester:/bin/bash" >> /etc/passwd echo "tester:x:101:" >> /etc/group install -o tester -d /home/tester
|
现在,赋予 bash 以名字(无故中二 XD):
exec /bin/bash --login +h
还要创建一些日志文件,虽然都是空的:
1 2 3 4
| 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
|
至此,初步配置完成,现在该安装额外工具了。
构建额外工具
你没理解错,以下部分全部都以root
用户编译。
GCC-11.2.0 中的 Libstdc++ - 第二遍
在前面第二遍编译 gcc 时,并没有编译它,因为它不能用宿主机工具链编译。
1 2
| tar -xvf gcc-11.2.0.tar.xz cd gcc-11.2.0
|
创建一个符号链接
ln -s gthr-posix.h libgcc/gthr-default.h
建立build
目录
configure
1 2 3 4 5 6 7
| ../libstdc++-v3/configure \ CXXFLAGS="-g -O2 -D_GNU_SOURCE" \ --prefix=/usr \ --disable-multilib \ --disable-nls \ --host=$(uname -m)-lfs-linux-gnu \ --disable-libstdcxx-pch
|
编译和安装
Gettext-0.21
这里只安装msgfmt
,msgmerge
,以及xgettext
这三个程序
1 2 3 4 5
| tar -xvf gettext-0.21.tar.xz cd gettext-0.21 ./configure --disable-shared make cp -v gettext-tools/src/{msgfmt,msgmerge,xgettext} /usr/bin
|
Bison-3.7.6
1 2
| tar -xvf bison-3.7.6.tar.xz cd bison-3.7.6
|
configure
1 2
| ./configure --prefix=/usr \ --docdir=/usr/share/doc/bison-3.7.6
|
编译和安装
Perl-5.34.0
此处要加一个 patch
1 2 3 4
| tar -xvf perl-5.34.0.tar.xz cp perl-5.34.0-upstream_fixes-1.patch perl-5.34.0/ cd perl-5.34.0 patch -Np1 -i perl-5.34.0-upstream_fixes-1.patch
|
configure
1 2 3 4 5 6 7 8 9
| sh Configure -des \ -Dprefix=/usr \ -Dvendorprefix=/usr \ -Dprivlib=/usr/lib/perl5/5.34/core_perl \ -Darchlib=/usr/lib/perl5/5.34/core_perl \ -Dsitelib=/usr/lib/perl5/5.34/site_perl \ -Dsitearch=/usr/lib/perl5/5.34/site_perl \ -Dvendorlib=/usr/lib/perl5/5.34/vendor_perl \ -Dvendorarch=/usr/lib/perl5/5.34/vendor_perl
|
编译和安装
Python-3.9.6
这里有两个 python 包,Python-3.9.6.tar.xz
和python-3.9.6-docs-html.tar.bz2
。
解压前面那个,后面的那个包因为没安装bzip2
无法解压。
注意区分大小写。
1 2
| tar -xvf Python-3.9.6.tar.xz cd Python-3.9.6
|
configure
1 2 3
| ./configure --prefix=/usr \ --enable-shared \ --without-ensurepip
|
编译和安装
这里有部分模块是无法编译的,但 make 还是会报错(还是 fatal error),这里只要最外面的 make 执行成功即可。
Texinfo-6.8
1 2
| tar -xvf texinfo-6.8.tar.xz cd texinfo-6.8
|
在编译之前,需要修复在使用 Glibc-2.34 或更新版本时编译会出现的问题
1 2
| sed -e 's/__attribute_nonnull__/__nonnull/' \ -i gnulib/lib/malloc/dynarray-skeleton.c
|
之后
1 2 3
| ./configure --prefix=/usr make make install
|
Util-linux-2.37.2
1 2
| tar -xvf util-linux-2.37.2.tar.xz cd util-linux-2.37.2
|
根据 FHS 的建议,使用/var/lib/hwclock
:
mkdir -pv /var/lib/hwclock
configure
1 2 3 4 5 6 7 8 9 10 11 12 13
| ./configure ADJTIME_PATH=/var/lib/hwclock/adjtime \ --libdir=/usr/lib \ --docdir=/usr/share/doc/util-linux-2.37.2 \ --disable-chfn-chsh \ --disable-login \ --disable-nologin \ --disable-su \ --disable-setpriv \ --disable-runuser \ --disable-pylibmount \ --disable-static \ --without-python \ runstatedir=/run
|
编译和安装
至此,额外的工具就构建完成了。
清理
首先清理文档
rm -rf /usr/share/{info,man,doc}/*
之后是libtool
的*.la
文件
find /usr/{lib,libexec} -name \*.la -delete
最后删除/tools
,现在已经不需要了
rm -rf /tools
备份
这是可选的,但小心一点总没错。
以下操作在 chroot 外进行,且使用root
用户。
exit
备份需要至少 1G 空间。
先解除内核虚拟文件系统的挂载:
1 2
| umount $LFS/dev{/pts,} umount $LFS/{sys,proc,run}
|
按照手册默认路径,备份于/root
1 2
| cd $LFS tar -cJpf $HOME/lfs-temp-tools-11.0-systemd.tar.xz .
|
还原
需要还原时,运行
1 2 3
| cd $LFS rm -rf ./* tar -xpf $HOME/lfs-temp-tools-11.0-systemd.tar.xz
|
运行前务必检查$LFS
是否正确设置!
不然你宿主系统就 gg 了,rm -rf /*
了解一下。
至此,构建临时系统部分结束。