对linux体系的东西知之甚少,想要借助LFS稍微入点门,督促自己学点linux的东西,所以才有了这个系列。
整个学习的过程,除了参考官网11.1版本的手册,也在B站看了点前辈们的操作视频,遇到新的知识点翻一翻鸟哥Linux私房菜,遇到报错最好是去google一下,毕竟是套广为流传的教程,基本上我遇到的问题别人也都遇到过。
准备工作首先是要有一台宿主机,本来我自己的机器弄个虚拟机什么也可以操作,但是思来想去还是去华为云上弄了个便宜的机器,挂载了两块50G的硬盘来弄。
LFS官网:www.linuxfromscratch.org/
分区
拿到机器和硬盘,第一件事情是要分区,云上机器默认的系统盘/dev/vda好像不允许我动,所以我又额外挂载了一个50G的硬盘。分区的目标是将新的数据盘/dev/vdb 挂在到/mnt/lfs目录下
查看当前分区信息
fdisk -l
[root@ecs-341537 ~]# fdisk -l
磁盘 /dev/vda:42.9 GB, 42949672960 字节,83886080 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x000a0e76
设备 Boot Start End Blocks Id System
/dev/vda1 * 2048 83886079 41942016 83 Linux
磁盘 /dev/vdb:42.9 GB, 42949672960 字节,83886080 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
进入分区工具
fdisk /dev/vdb
[root@ecs-341537 ~]# fdisk /dev/vdb
欢迎使用 fdisk (util-linux 2.23.2)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
Device does not contain a recognized partition table
使用磁盘标识符 0xce13e1c3 创建新的 DOS 磁盘标签。
命令(输入 m 获取帮助):p
磁盘 /dev/vdb:42.9 GB, 42949672960 字节,83886080 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xce13e1c3
设备 Boot Start End Blocks Id System
命令(输入 m 获取帮助):n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
分区号 (1-4,默认 1):
起始 扇区 (2048-83886079,默认为 2048):
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-83886079,默认为 83886079):
将使用默认值 83886079
分区 1 已设置为 Linux 类型,大小设为 40 GiB
分区完成,输入"p"查看信息
命令(输入 m 获取帮助):p
磁盘 /dev/vdb:42.9 GB, 42949672960 字节,83886080 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xce13e1c3
设备 Boot Start End Blocks Id System
/dev/vdb1 2048 83886079 41942016 83 Linux
输入"w",按"Enter",将分区结果写入分区表中
命令(输入 m 获取帮助):w
The partition table has been altered!
Calling ioctl() to re-read partition table.
正在同步磁盘。
执行partprobe命令,将新的分区表变更同步至操作系统。
[root@ecs-341537 ~]# partprobe
[root@ecs-341537 ~]# fdisk -l
磁盘 /dev/vda:42.9 GB, 42949672960 字节,83886080 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x000a0e76
设备 Boot Start End Blocks Id System
/dev/vda1 * 2048 83886079 41942016 83 Linux
磁盘 /dev/vdb:42.9 GB, 42949672960 字节,83886080 个扇区
Units = 扇区 of 1 * 512 = 512 bytes
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xce13e1c3
设备 Boot Start End Blocks Id System
/dev/vdb1 2048 83886079 41942016 83 Linux
格式化
ext4 格式化
[root@ecs-341537 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 40G 0 disk
└─vda1 253:1 0 40G 0 part /
vdb 253:16 0 40G 0 disk
└─vdb1 253:17 0 40G 0 part
[root@ecs-341537 ~]# mkfs -t ext4 /dev/vdb1
mke2fs 1.42.9 (28-Dec-2013)
文件系统标签=
OS type: Linux
块大小=4096 (log=2)
分块大小=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
2621440 inodes, 10485504 blocks
524275 blocks (5.00%) reserved for the super user
第一个数据块=0
Maximum filesystem blocks=2157969408
320 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624
Allocating group tables: 完成
正在写入inode表: 完成
Creating journal (32768 blocks): 完成
Writing superblocks and filesystem accounting information: 完成
挂载
[root@ecs-341537 ~]# mkdir /mnt/lfs
[root@ecs-341537 ~]# mount /dev/vdb1 /mnt/lfs/
[root@ecs-341537 ~]# df -TH
文件系统 类型 容量 已用 可用 已用% 挂载点
devtmpfs devtmpfs 953M 0 953M 0% /dev
tmpfs tmpfs 964M 0 964M 0% /dev/shm
tmpfs tmpfs 964M 9.0M 955M 1% /run
tmpfs tmpfs 964M 0 964M 0% /sys/fs/cgroup
/dev/vda1 ext4 43G 2.7G 38G 7% /
tmpfs tmpfs 193M 0 193M 0% /run/user/0
/dev/vdb1 ext4 43G 51M 40G 1% /mnt/lfs
云服务器重启后,挂载会失效,需要设置开机自动挂载
查询uuid
[root@ecs-341537 ~]# blkid /dev/vdb1
/dev/vdb1: UUID="39980c95-692b-4214-8954-f823bc88f5fc" TYPE="ext4"
vi /etc/fstab 编辑
#
# /etc/fstab
# Created by anaconda on Mon Feb 14 02:14:30 2022
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=16ecf522-4607-452f-8e42-ea6b728c6d45 / ext4 defaults 1 1
UUID=39980c95-692b-4214-8954-f823bc88f5fc /mnt/lfs ext4 defaults 0 2
宿主机环境配置
分区弄好以后,先把宿主机环境要求的软件和版本都准备好,然后去把lfs11.1的源码下载下来。
宿主机软件要求
检查脚本
cat > version-check.sh << "EOF"
#!/bin/bash
# Simple script to list version numbers of critical development tools
export LC_ALL=C
bash --version | head -n1 | cut -d" " -f2-4
MYSH=$(readlink -f /bin/sh)
echo "/bin/sh -> $MYSH"
echo $MYSH | grep -q bash || echo "ERROR: /bin/sh does not point to bash"
unset MYSH
echo -n "Binutils: "; ld --version | head -n1 | cut -d" " -f3-
bison --version | head -n1
if [ -h /usr/bin/yacc ]; then
echo "/usr/bin/yacc -> `readlink -f /usr/bin/yacc`";
elif [ -x /usr/bin/yacc ]; then
echo yacc is `/usr/bin/yacc --version | head -n1`
else
echo "yacc not found"
fi
echo -n "Coreutils: "; chown --version | head -n1 | cut -d")" -f2
diff --version | head -n1
find --version | head -n1
gawk --version | head -n1
if [ -h /usr/bin/awk ]; then
echo "/usr/bin/awk -> `readlink -f /usr/bin/awk`";
elif [ -x /usr/bin/awk ]; then
echo awk is `/usr/bin/awk --version | head -n1`
else
echo "awk not found"
fi
gcc --version | head -n1
g++ --version | head -n1
grep --version | head -n1
gzip --version | head -n1
cat /proc/version
m4 --version | head -n1
make --version | head -n1
patch --version | head -n1
echo Perl `perl -V:version`
python3 --version
sed --version | head -n1
tar --version | head -n1
makeinfo --version | head -n1 # texinfo version
xz --version | head -n1
echo 'int main(){}' > dummy.c && g++ -o dummy dummy.c
if [ -x dummy ]
then echo "g++ compilation OK";
else echo "g++ compilation failed"; fi
rm -f dummy.c dummy
EOF
bash version-check.sh
安装通过yum -y install 安装就好了 yacc 需要通过链接的方式
[root@ecs-341537 ~]# ln -sv /usr/bin/bison /usr/bin/yacc
"/usr/bin/yacc" -> "/usr/bin/bison"
另外,make 要求4.0, 我们这里版本是3.82
[root@ecs-341537 ~]# cd /tmp
[root@ecs-341537 tmp]# wget http://mirrors.ustc.edu.cn/gnu/make/make-4.0.tar.gz
[root@ecs-341537 tmp]# tar -xf make-4.0.tar.gz
[root@ecs-341537 tmp]# cd make-4.0
[root@ecs-341537 make-4.0]# ./configure
[root@ecs-341537 make-4.0]# make && make install
安装完了还没完,检查下版本发现还是3.82
[root@ecs-341537 make-4.0]# make -v
GNU Make 3.82
Built for x86_64-redhat-linux-gnu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
[root@ecs-341537 make-4.0]# whereis make
make: /usr/bin/make /usr/local/bin/make /usr/share/man/man1/make.1.gz
[root@ecs-341537 make-4.0]# cd /usr/bin/
[root@ecs-341537 bin]# mv make make.bak
[root@ecs-341537 bin]# ln -sv /usr/local/bin/make /usr/bin/make
"/usr/bin/make" -> "/usr/local/bin/make"
[root@ecs-341537 bin]# make -v
GNU Make 4.0
Built for x86_64-unknown-linux-gnu
Copyright (C) 1988-2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
设置环境变量
www.linuxfromscratch.org/lfs/view/11…
[root@ecs-341537 ~]# export LFS=/mnt/lfs
[root@ecs-341537 ~]# echo $LFS
/mnt/lfs
创建放源码的目录
www.linuxfromscratch.org/lfs/view/11…
[root@ecs-341537 ~]# mkdir -v $LFS/sources
mkdir: 已创建目录 "/mnt/lfs/sources"
[root@ecs-341537 ~]# chmod -v a+wt $LFS/sources
mode of "/mnt/lfs/sources" changed from 0755 (rwxr-xr-x) to 1777 (rwxrwxrwt)
[root@ecs-341537 ~]# cd /mnt/lfs/sources/
下载和解压11.1 tar包
下载地址 mirrors.ustc.edu.cn/
[root@ecs-341537 sources]# wget https://mirrors.ustc.edu.cn/lfs/lfs-packages/lfs-packages-11.1.tar
--2022-07-23 02:03:23-- https://mirrors.ustc.edu.cn/lfs/lfs-packages/lfs-packages-11.1.tar
正在解析主机 mirrors.ustc.edu.cn (mirrors.ustc.edu.cn)... 202.141.176.110, 202.141.160.110, 2001:da8:d800:95::110
正在连接 mirrors.ustc.edu.cn (mirrors.ustc.edu.cn)|202.141.176.110|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:482498560 (460M) [application/octet-stream]
正在保存至: “lfs-packages-11.1.tar”
10% [======> ] 50,601,690 1.29MB/s 剩余 66s
解压
[root@ecs-341537 sources]# tar -xf lfs-packages-11.1.tar
[root@ecs-341537 sources]# ll
总用量 471196
drwxrwxr-x 2 1000 1000 4096 3月 1 11:37 11.1
-rw-r--r-- 1 root root 482498560 3月 1 11:42 lfs-packages-11.1.tar
将11.1 文件夹下的文件移动到sources文件夹下
[root@ecs-341537 sources]# mv 11.1/* .
[root@ecs-341537 sources]# rm -rf 11.1 lfs-packages-11.1.tar
到这里,记得创建一个镜像。
www.linuxfromscratch.org/lfs/view/11…
创建临时系统
建目录
在$LFS环境中创建一系列目录
[root@ecs-341537 sources]# mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}
mkdir: 已创建目录 "/mnt/lfs/etc"
mkdir: 已创建目录 "/mnt/lfs/var"
mkdir: 已创建目录 "/mnt/lfs/usr"
mkdir: 已创建目录 "/mnt/lfs/usr/bin"
mkdir: 已创建目录 "/mnt/lfs/usr/lib"
mkdir: 已创建目录 "/mnt/lfs/usr/sbin"
[root@ecs-341537 sources]# for i in bin lib sbin; do
> ln -sv usr/$i $LFS/$i
> done
"/mnt/lfs/bin" -> "usr/bin"
"/mnt/lfs/lib" -> "usr/lib"
"/mnt/lfs/sbin" -> "usr/sbin"
[root@ecs-341537 sources]# case $(uname -m) in
> x86_64) mkdir -pv $LFS/lib64 ;;
> esac
mkdir: 已创建目录 "/mnt/lfs/lib64"
mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}
for i in bin lib sbin; do
ln -sv usr/$i $LFS/$i
done
case $(uname -m) in
x86_64) mkdir -pv $LFS/lib64 ;;
esac
查看目录结构
[root@ecs-341537 lfs]# mkdir -pv $LFS/tools
mkdir: 已创建目录 "/mnt/lfs/tools"
[root@ecs-341537 lfs]# ll
总用量 40
lrwxrwxrwx 1 root root 7 7月 23 02:17 bin -> usr/bin
drwxr-xr-x 2 root root 4096 7月 23 02:17 etc
lrwxrwxrwx 1 root root 7 7月 23 02:17 lib -> usr/lib
drwxr-xr-x 2 root root 4096 7月 23 02:17 lib64
drwx------ 2 root root 16384 7月 23 01:29 lost+found
lrwxrwxrwx 1 root root 8 7月 23 02:17 sbin -> usr/sbin
drwxrwxrwt 2 root root 4096 7月 23 02:18 sources
drwxr-xr-x 2 root root 4096 7月 23 02:20 tools
drwxr-xr-x 5 root root 4096 7月 23 02:17 usr
drwxr-xr-x 2 root root 4096 7月 23 02:17 var
建无特权的账号
[root@ecs-341537 lfs]# groupadd lfs
[root@ecs-341537 lfs]# useradd -s /bin/bash -g lfs -m -k /dev/null lfs
-s /bin/bash 指定用户登入后所使用的shell。 -g lfs 指定用户所属的群组。 -m 自动建立用户的登入home目录 -k /dev/null lfs 用户名
设置lfs用户的密码
[root@ecs-341537 lfs]# passwd lfs
设置权限
[root@ecs-341537 lfs]# chown -v lfs $LFS/{usr{,/*},lib,var,etc,bin,sbin,tools}
changed ownership of "/mnt/lfs/usr" from root to lfs
changed ownership of "/mnt/lfs/usr/bin" from root to lfs
changed ownership of "/mnt/lfs/usr/lib" from root to lfs
changed ownership of "/mnt/lfs/usr/sbin" from root to lfs
"/mnt/lfs/lib" 的所有者已保留为lfs
changed ownership of "/mnt/lfs/var" from root to lfs
changed ownership of "/mnt/lfs/etc" from root to lfs
"/mnt/lfs/bin" 的所有者已保留为lfs
"/mnt/lfs/sbin" 的所有者已保留为lfs
changed ownership of "/mnt/lfs/tools" from root to lfs
[root@ecs-341537 lfs]# case $(uname -m) in
> x86_64) chown -v lfs $LFS/lib64 ;;
> esac
changed ownership of "/mnt/lfs/lib64" from root to lfs
[root@ecs-341537 lfs]# chown -v lfs $LFS/sources
changed ownership of "/mnt/lfs/sources" from root to lfs
接下来以lfs的身份登录
[root@ecs-341537 lfs]# su - lfs
-bash-4.2$
-bash-4.2$ whoami
lfs
设置环境
-bash-4.2$ cat > ~/.bash_profile << "EOF"
> exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
> EOF
-bash-4.2$ echo $HOME
/home/lfs
-bash-4.2$ echo $TERM
xterm-256color
-bash-4.2$ echo PS1
PS1
-bash-4.2$ cat > ~/.bashrc << "EOF"
> set +h
> umask 022
> LFS=/mnt/lfs
> LC_ALL=POSIX
> LFS_TGT=$(uname -m)-lfs-linux-gnu
> PATH=/usr/bin
> if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
> PATH=$LFS/tools/bin:$PATH
> CONFIG_SITE=$LFS/usr/share/config.site
> export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
> EOF
切换到root用户
-bash-4.2$ exit
logout
[root@ecs-341537 lfs]# whoami
root
[root@ecs-341537 lfs]# [ ! -e /etc/bash.bashrc ] || mv -v /etc/bash.bashrc /etc/bash.bashrc.NOUSE
切换回lfs用户
[root@ecs-341537 etc]# su - lfs
lfs:~$ source ~/.bash_profile
lfs:~$ echo $LFS
/mnt/lfs
lfs:~$ echo $PATH
/mnt/lfs/tools/bin:/usr/bin
查看当前.bashrc
lfs:~$ ls -a
. .. .bash_history .bash_profile .bashrc
lfs:~$ cat .bashrc
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
设置多线程处理make 其实这里设置以后多半有坑,我的机器cpu和内存有限,在后面编译gcc的时候就反复遇到瓶颈。 直接用-j1可能还少点麻烦
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
MAKEFLAGS='-j4'
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE MAKEFLAGS
使设置生效
lfs:~$ source .bashrc
lfs:~$ set | grep MAKEFLAGS
MAKEFLAGS=-j4