- 由 虚拟的现实创建于5月 10, 2025 需要 6 分钟阅读时间
1. 简介
参照 4014-LFS 自定义 Linux(上)和 4015-LFS 自定义 Linux (中) 完成了自定义的 Linux 后,当你想用这个 LFS 做点啥的时候会发现很尴尬,因为它只提供了最基础的指令和功能。在当前的情况下还只能在本地主机的显示界面操作,因为它连 wget 和 ssh 这类的工具都没有。
严格来说接下来的内容是 BLFS 项目的内容了,BLFS 是在 LFS 的基础上按使用需求自定义配置应用场景的组件,包括安全、图像、开发工具、办公等不同的应用场景。这里的内容主要解决以下的问题
- 解决进入 LFS 系统后命令提示符显示 bash-5.2 这样的内容
- 确保能正常联网,能被内网的其它机器访问
- 提供 ssh 接入
- 编译 wget 等基础工具
- 后续能在这个基础镜像上逐步完善
1.1. 使用 LFS 系统的命令行工作
这种方法需要先使用 chroot 安装 libtasn1,p11-kit,make-ca,wget,gpm,以及 links (或者 lynx),然后重启计算机,进入新的 LFS 系统。 LFS 系统默认有六个虚拟控制台。可以使用 Alt+Fx 组合键切换控制台,其中 Fx 是 F1 到 F6 之间的键。Alt+← 和 Alt+→ 组合键也可以切换控制台。
此时,可以在两个不同的虚拟控制台登录,在其中一个运行 links 或 lynx 浏览器,另一个运行 bash。GPM 允许使用鼠标左键选择并复制浏览器中的命令,然后可以切换终端,将命令粘贴到另一个终端中运行。
2. 切换宿主机
在 LFS 主机环境,即使网络正常,但是由于没有 wget 和 curl 之类的下载工具,想要安装 SSH 非常麻烦(LFS 项目中没有 ssh 应用)。那就先将 LFS 关机重新将宿主机的硬盘挂载上去。开机后就是宿主机的环境了。
- 【debian12.vdi】和 【lfs.vdi】同时存在,系统启动后自动进入宿主机,LFS 硬盘显示为 /dev/sdb
- 【lfs.vdi】单独存在,系统启动后进入 LFS 主机,LFS 硬盘为 /dev/sda
切换宿主机后需要检查环境变量并进入 chroot 环境,确保针对 LFS 操作
export LFS=/mnt/lfs echo $LFS mount -v -t ext4 /dev/sdb3 $LFS mount -v --bind /dev $LFS/dev mount -vt devpts devpts -o gid=5,mode=0620 $LFS/dev/pts mount -vt proc proc $LFS/proc mount -vt sysfs sysfs $LFS/sys mount -vt tmpfs tmpfs $LFS/run if [ -h $LFS/dev/shm ]; then install -v -d -m 1777 $LFS$(realpath /dev/shm) else mount -vt tmpfs -o nosuid,nodev tmpfs $LFS/dev/shm fi chroot "$LFS" /usr/bin/env -i \ HOME=/root \ TERM="$TERM" \ PS1='(lfs chroot) \u:\w\$ ' \ PATH=/usr/bin:/usr/sbin \ MAKEFLAGS="-j$(nproc)" \ TESTSUITEFLAGS="-j$(nproc)" \ /bin/bash --login
3. 配置 LFS 环境变量
以下的操作是 chroot 方式下针对 LFS 的操作。当然,不使用宿主机直接在 LFS 主机下操作也是可以的。
3.1. /etc/profile
cat > /etc/profile << "EOF" # Begin /etc/profile pathremove () { local IFS=':' local NEWPATH local DIR local PATHVARIABLE=${2:-PATH} for DIR in ${!PATHVARIABLE} ; do if [ "$DIR" != "$1" ] ; then NEWPATH=${NEWPATH:+$NEWPATH:}$DIR fi done export $PATHVARIABLE="$NEWPATH" } pathprepend () { pathremove $1 $2 local PATHVARIABLE=${2:-PATH} export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}" } pathappend () { pathremove $1 $2 local PATHVARIABLE=${2:-PATH} export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1" } export -f pathremove pathprepend pathappend # Set the initial path export PATH=/usr/bin # Attempt to provide backward compatibility with LFS earlier than 11 if [ ! -L /bin ]; then pathappend /bin fi if [ $EUID -eq 0 ] ; then pathappend /usr/sbin if [ ! -L /sbin ]; then pathappend /sbin fi unset HISTFILE fi # Set up some environment variables. export HISTSIZE=1000 export HISTIGNORE="&:[bf]g:exit" # Set some defaults for graphical systems export XDG_DATA_DIRS=${XDG_DATA_DIRS:-/usr/share} export XDG_CONFIG_DIRS=${XDG_CONFIG_DIRS:-/etc/xdg} export XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-/tmp/xdg-$USER} for script in /etc/profile.d/*.sh ; do if [ -r $script ] ; then . $script fi done unset script 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
3.2. /etc/profile.d/bash_completion.sh
install --directory --mode=0755 --owner=root --group=root /etc/profile.d cat > /etc/profile.d/bash_completion.sh << "EOF" # Begin /etc/profile.d/bash_completion.sh # Import bash completion scripts # If the bash-completion package is installed, use its configuration instead if [ -f /usr/share/bash-completion/bash_completion ]; then # Check for interactive bash and that we haven't already been sourced. if [ -n "${BASH_VERSION-}" -a -n "${PS1-}" -a -z "${BASH_COMPLETION_VERSINFO-}" ]; then # Check for recent enough version of bash. if [ ${BASH_VERSINFO[0]} -gt 4 ] || \ [ ${BASH_VERSINFO[0]} -eq 4 -a ${BASH_VERSINFO[1]} -ge 1 ]; then [ -r "${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion" ] && \ . "${XDG_CONFIG_HOME:-$HOME/.config}/bash_completion" if shopt -q progcomp && [ -r /usr/share/bash-completion/bash_completion ]; then # Source completion code. . /usr/share/bash-completion/bash_completion fi fi fi else # bash-completions are not installed, use only bash completion directory if shopt -q progcomp; then for script in /etc/bash_completion.d/* ; do if [ -r $script ] ; then . $script fi done fi fi # End /etc/profile.d/bash_completion.sh EOF install --directory --mode=0755 --owner=root --group=root /etc/bash_completion.d
3.3. /etc/profile.d/dircolors.sh
cat > /etc/profile.d/dircolors.sh << "EOF" # Setup for /bin/ls and /bin/grep to support color, the alias is in /etc/bashrc. if [ -f "/etc/dircolors" ] ; then eval $(dircolors -b /etc/dircolors) fi if [ -f "$HOME/.dircolors" ] ; then eval $(dircolors -b $HOME/.dircolors) fi EOF
3.4. /etc/profile.d/extrapaths.sh
cat > /etc/profile.d/extrapaths.sh << "EOF" if [ -d /usr/local/lib/pkgconfig ] ; then pathappend /usr/local/lib/pkgconfig PKG_CONFIG_PATH fi if [ -d /usr/local/bin ]; then pathprepend /usr/local/bin fi if [ -d /usr/local/sbin -a $EUID -eq 0 ]; then pathprepend /usr/local/sbin fi if [ -d /usr/local/share ]; then pathprepend /usr/local/share XDG_DATA_DIRS fi # Set some defaults before other applications add to these paths. pathappend /usr/share/info INFOPATH EOF
3.5. /etc/profile.d/readline.sh
cat > /etc/profile.d/readline.sh << "EOF" # Set up the INPUTRC environment variable. if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ] ; then INPUTRC=/etc/inputrc fi export INPUTRC EOF
3.6. /etc/profile.d/umask.sh
cat > /etc/profile.d/umask.sh << "EOF" # By default, the umask should be set. if [ "$(id -gn)" = "$(id -un)" -a $EUID -gt 99 ] ; then umask 002 else umask 022 fi EOF
3.7. /etc/profile.d/i18n.sh
cat > /etc/profile.d/i18n.sh << "EOF" # Set up i18n variables 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 EOF
3.8. /etc/bashrc
cat > /etc/bashrc << "EOF" # Begin /etc/bashrc # Provides colored /bin/ls and /bin/grep commands. Used in conjunction # with code in /etc/profile. alias ls='ls --color=auto' alias grep='grep --color=auto' # Provides prompt for interactive shells, specifically shells started # in the X environment. [Review the LFS archive thread titled # PS1 Environment Variable for a great case study behind this script # addendum.] NORMAL="\[\e[0m\]" RED="\[\e[1;31m\]" GREEN="\[\e[1;32m\]" if [[ $EUID == 0 ]] ; then PS1="$RED\u [ $NORMAL\w$RED ]# $NORMAL" else PS1="$GREEN\u [ $NORMAL\w$GREEN ]\$ $NORMAL" fi unset RED GREEN NORMAL # GnuPG wants this or it'll fail with pinentry-curses under some # circumstances (for example signing a Git commit) tty -s && export GPG_TTY=$(tty) # End /etc/bashrc EOF
3.9. ~/.bash_profile
cat > ~/.bash_profile << "EOF" # Begin ~/.bash_profile # System wide aliases and functions are in /etc/bashrc. if [ -f "$HOME/.bashrc" ] ; then source $HOME/.bashrc fi if [ -d "$HOME/bin" ] ; then pathprepend $HOME/bin fi # Having . in the PATH is dangerous #if [ $EUID -gt 99 ]; then # pathappend . #fi # End ~/.bash_profile EOF
3.10. ~/.profile
cat > ~/.profile << "EOF" # Begin ~/.profile # Personal environment variables and startup programs. if [ -d "$HOME/bin" ] ; then pathprepend $HOME/bin fi # Set up user specific i18n variables #export LANG=<ll>_<CC>.<charmap><@modifiers> # End ~/.profile EOF
3.11. ~/.bashrc
cat > ~/.bashrc << "EOF" # Begin ~/.bashrc # programs are in /etc/profile. System wide aliases and functions are # in /etc/bashrc. if [ -f "/etc/bashrc" ] ; then source /etc/bashrc fi # Set up user specific i18n variables #export LANG=<ll>_<CC>.<charmap><@modifiers> # End ~/.bashrc EOF
3.12. ~/.bash_logout
cat > ~/.bash_logout << "EOF" # Begin ~/.bash_logout # Written for Beyond Linux From Scratch # by James Robertson <jameswrobertson@earthlink.net> # Personal items to perform on logout. # End ~/.bash_logout EOF dircolors -p > /etc/dircolors
4. 安全工具
4.1. OpenSSH-9.9p2
请在宿主机环境下载 openssh 源码,因为 chroot 环境下没有 wget 网络工具。建议同时下载后续需要使用的 wget 和 blfs 相关的启用脚本文件
logout cd $LFS/sources wget https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-9.9p2.tar.gz https://anduin.linuxfromscratch.org/BLFS/blfs-bootscripts/blfs-bootscripts-20250225.tar.xz wget https://ftp.gnu.org/gnu/wget/wget-1.25.0.tar.gz
完成源码下载后参照切换宿主机方式进入 chroot 环境。以下的操作都是在 chroot 环境或者在独立的 lfs 主机环境下操作
cd /sources tar xvf openssh-9.9p2.tar.gz cd openssh-9.9p2 install -v -g sys -m700 -d /var/lib/sshd && groupadd -g 50 sshd && useradd -c 'sshd PrivSep' \ -d /var/lib/sshd \ -g sshd \ -s /bin/false \ -u 50 sshd ./configure --prefix=/usr \ --sysconfdir=/etc/ssh \ --with-privsep-path=/var/lib/sshd \ --with-default-path=/usr/bin \ --with-superuser-path=/usr/sbin:/usr/bin \ --with-pid-dir=/run && make make install && install -v -m755 contrib/ssh-copy-id /usr/bin && install -v -m644 contrib/ssh-copy-id.1 \ /usr/share/man/man1 echo "PermitRootLogin yes" >> /etc/ssh/sshd_config tar xvf blfs-bootscripts-20250225.tar.xz cd blfs-bootscripts-20250225 make install-sshd
make install-sshd 是通过脚本自动生成启动配置
如果不想开机自启动也可以在进入 LFS 后执行 /usr/sbin/sshd 启动
4.2. p11-kit-0.25.5
wget https://github.com/p11-glue/p11-kit/releases/download/0.25.5/p11-kit-0.25.5.tar.xz --no-check-certificate tar xvf p11-kit-0.25.5.tar.xz cd p11-kit-0.25.5 sed '20,$ d' -i trust/trust-extract-compat && cat >> trust/trust-extract-compat << "EOF" # Copy existing anchor modifications to /etc/ssl/local /usr/libexec/make-ca/copy-trust-modifications # Update trust stores /usr/sbin/make-ca -r EOF mkdir p11-build && cd p11-build && meson setup .. \ --prefix=/usr \ --buildtype=release \ -D trust_paths=/etc/pki/anchors && ninja ninja install && ln -sfv /usr/libexec/p11-kit/trust-extract-compat \ /usr/bin/update-ca-certificates ln -sfv ./pkcs11/p11-kit-trust.so /usr/lib/libnssckbi.so
4.3. make-ca-1.16
tar xvf make-ca-1.16.tar.gz cd make-ca-1.16 make install && install -vdm755 /etc/ssl/local /usr/sbin/make-ca -g cat > /etc/cron.weekly/update-pki.sh << "EOF" && #!/bin/bash /usr/sbin/make-ca -g EOF chmod 754 /etc/cron.weekly/update-pki.sh wget http://www.cacert.org/certs/root.crt && wget http://www.cacert.org/certs/class3.crt && openssl x509 -in root.crt -text -fingerprint -setalias "CAcert Class 1 root" \ -addtrust serverAuth -addtrust emailProtection -addtrust codeSigning \ > /etc/ssl/local/CAcert_Class_1_root.pem && openssl x509 -in class3.crt -text -fingerprint -setalias "CAcert Class 3 root" \ -addtrust serverAuth -addtrust emailProtection -addtrust codeSigning \ > /etc/ssl/local/CAcert_Class_3_root.pem && /usr/sbin/make-ca -r
5. 网络工具
5.1. Wget-1.25.0
tar xvf wget-1.25.0.tar.gz cd wget-1.25.0 ./configure --prefix=/usr \ --sysconfdir=/etc \ --with-ssl=openssl && make make install
5.2. Lynx-2.9.2
tar xvf lynx2.9.2.tar.bz2 cd lynx2.9.2 ./configure --prefix=/usr \ --sysconfdir=/etc/lynx \ --with-zlib \ --with-bzlib \ --with-ssl \ --with-screen=ncursesw \ --enable-locale-charset \ --datadir=/usr/share/doc/lynx-2.9.2 && make make install-full sed -e '/#LOCALE/ a LOCALE_CHARSET:TRUE' \ -i /etc/lynx/lynx.cfg sed -e '/#DEFAULT_ED/ a DEFAULT_EDITOR:vi' \ -i /etc/lynx/lynx.cfg sed -e '/#PERSIST/ a PERSISTENT_COOKIES:TRUE' \ -i /etc/lynx/lynx.cfg
6. 通用库
6.1. libtasn1-4.20.0
cd /sources/ wget https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.20.0.tar.gz --no-check-certificate tar xvf libtasn1-4.20.0.tar.gz cd libtasn1-4.20.0 ./configure --prefix=/usr --disable-static && make make install
7. 系统工具
7.1. GPM-1.20.7
需要确保内核已启用 mouse 功能
Device Drivers --->
Input device support --->
-*- Generic input layer (needed for keyboard, mouse, ...) [INPUT]
<*/M> Mouse interface [INPUT_MOUSEDEV]
wget https://anduin.linuxfromscratch.org/BLFS/gpm/gpm-1.20.7.tar.bz2 wget https://www.linuxfromscratch.org/patches/blfs/12.3/gpm-1.20.7-consolidated-1.patch tar xvf gpm-1.20.7.tar.bz2 cd gpm-1.20.7 patch -Np1 -i ../gpm-1.20.7-consolidated-1.patch && ./autogen.sh && ./configure --prefix=/usr --sysconfdir=/etc ac_cv_path_emacs=no && make make install && install-info --dir-file=/usr/share/info/dir \ /usr/share/info/gpm.info && rm -fv /usr/lib/libgpm.a && ln -sfv libgpm.so.2.1.0 /usr/lib/libgpm.so && install -v -m644 conf/gpm-root.conf /etc cd blfs-bootscripts-20250225 make install-gdm
- 无标签
添加评论