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



  • 无标签
写评论...