阅读更多
1 镜像站
1.1 网易开源镜像站
以CentOS-7.7.1908
为例,下载地址为:http://mirrors.163.com/centos/7.7.1908/isos/x86_64/CentOS-7-x86_64-Minimal-1908.iso
1.2 阿里云镜像站
以ubuntu-18.04.6
为例,下载地址为:https://mirrors.aliyun.com/ubuntu-releases/bionic/ubuntu-18.04.6-desktop-amd64.iso
1.3 centos镜像站
以CentOS-7.7.1908
为例,下载地址列表为:http://isoredirect.centos.org/centos/7.7.1908/isos/x86_64/
2 CentOS装机
博主安装的是minimal版本
- 配网,修改
/etc/sysconfig/network-scripts/ifcfg-enp0s3
,将ONBOOT
修改为yes
,然后执行systemctl restart network
- 安装网络工具包
yum install -y net-tools.x86_64
- 安装vim
yum install -y vim
2.1 配置分区容量
默认情况下,CentOS会给根分区分配50G的容量,剩余容量则分配给home分区,我们可以通过一组命令简单得调整一下分区容量
仍然保留两个分区,将大部分的容量都分配给根分区
1 | # 1/11: 备份home分区文件 |
只保留根分区,/home只作为根分区的一个目录
1 | # 1/9: 备份home分区文件 |
2.2 LVM扩容
2.2.1 fdisk
1 | fdisk -l |
2.2.2 parted
fdisk
最多只能添加容量小于2TB的硬盘,当需要添加大于2TB容量的硬盘时,需要使用parted
1 | fdisk -l |
2.3 LVM缩容
缩容需谨慎,一不小心就会导致系统整个无法使用
1 | # 将lvm的容量缩小 |
2.4 修复因断电导致磁盘inode损坏
步骤
- 进入
emergency
模式- 在CentOS的boot菜单下按
e
,并编辑grub命令,在linux16
配置项最后追加systemd.unit=emergency.target
,按Ctrl+x
即可进入emergency
模式
- 在CentOS的boot菜单下按
- 找到
Linux LVM
的根分区地址和设备 cat /etc/fstab
确定根分区文件系统类型,通常为ext4
或xfs
- 若文件系统为
ext4
,运行fsck -f
,例如fsck -f /dev/mapper/centos-root
- 若文件系统为
xfs
,运行xfs_repair -v /dev/mapper/centos-root
- 针对根分区已加载的情况下,可以执行
xfs_repair -d /dev/mapper/centos-root
尝试修复 - 如果修复失败,可以添加参数
-L
进行修复,但是这样会丢失一部分文件系统日志,不建议一开始就尝试,可以作为最终解决方案
- 针对根分区已加载的情况下,可以执行
- 若文件系统为
2.5 忘记root密码
方法1
- 进入
Single User && Emergency
模式- 在CentOS的boot菜单下按
e
,并编辑grub命令,在linux16
配置项最后追加rw init=/sysroot/bin/bash
,按Ctrl+x
即可进入rw
表示以可读写的方式挂载根分区init=/sysroot/bin/bash
:系统安装所在分区里面路径为/bin/bash
的文件,内核启动过程中会查找系统安装所在分区,然后把该分区挂载到/sysroot
目录下
- 在CentOS的boot菜单下按
- 修改密码
chroot /sysroot
passwd
:修改密码,键入两次新密码即可touch /.autorelabel
exit
reboot -f
touch /.autorelabel
这个命令有什么作用:当我们用passwd
修改密码时,/etc/shadow
文件会在错误的SELinux
上下文中被修改。touch /.autorelabel
命令会创建一个隐藏文件,在下次启动时,SELinux
子系统将检测到该文件,然后使用正确的SELinux
上下文重新标记文件系统上的所有文件。在大磁盘上,此过程可能消耗大量的时间
方法2
- 进入
Single User
模式- 在CentOS的boot菜单下按
e
,并编辑grub命令,在linux16
配置项最后追加init=/bin/bash
,按Ctrl+x
即可进入init=/bin/bash
:内核启动过程中临时文件系统(initrd.img
)里面路径为/bin/bash
的文件
- 在CentOS的boot菜单下按
- 修改密码
mount -o remount,rw /
:重新以rw
的方式挂载根分区(因为这次,我们没有在内核参数中增加rw
参数)passwd
:修改密码,键入两次新密码即可touch /.autorelabel
/sbin/reboot -f
方法3
- 进入
Single User && Emergency
模式- 在CentOS的boot菜单下按
e
,并编辑grub命令,在linux16
配置项最后追加rd.break
,按Ctrl+x
即可进入rd.break
:rd
指的是init ram disk
;break
指的是boot
程序在将控制权从initramfs
转交给systemd
之前进行中断
- 在CentOS的boot菜单下按
- 修改密码
mount -o remount,rw /sysroot
:重新以rw
的方式挂载根分区(因为这次,我们没有在内核参数中增加rw
参数)chroot /sysroot
passwd
touch /.autorelabel
exit
reboot -f
2.6 恢复boot分区
当boot分区不小心被破坏之后(比如,用fdisk将boot分区误删了),机器是无法启动成功的,会出现如下错误页面
可以通过以下步骤进行恢复
第一步:找到系统的iso,并制作u盘启动盘。插入u盘后开机
第二步:在grub菜单页,依次选择Troubleshooting
、Rescue a CentOS system
第三步:从u盘启动linux系统,并获取shell
第四步:重新安装grub以及grub配置文件
1 | # 硬盘的挂载点是/mnt/sysimage |
第五步(可选):这一步取决于boot分区是如何被破坏的,如果整个分区都删掉了,那么需要修改/etc/fstab
将/boot
分区的配置项注释掉,然后重启
2.7 概念理解
- 物理卷(physics volume)
- 可以用
pvdisplay
查看逻辑卷
- 可以用
- 卷组(volume group)
- 可以用
vgdisplay
查看逻辑卷
- 可以用
- 逻辑卷(logical volume)
- 可以用
lvdisplay
查看逻辑卷 - 上面出现的
/dev/centos/root
就是逻辑卷,而/dev/mapper/centos-root
其实是一个逻辑磁盘(dm
就是device mapper
的缩写)/dev/mapper/centos-root
其实是个链接文件,链接到了/dev/dm-0
,在你的电脑上可能不是0
dmsetup info /dev/dm-0
可以查看/dev/dm-0
的信息sudo lvdisplay|awk '/LV Name/{n=$3} /Block device/{d=$3; sub(".*:","dm-",d); print d,n;}'
可以查看映射关系
- 可以用
2.8 参考
- CentOS 7 调整 home分区 扩大 root分区
- 手把手教你给 CentOS 7 添加硬盘及扩容(LVM)
- Linux Creating a Partition Size Larger Than 2TB
- What is this dm-0 device?(/dev/mapper/centos-root以及/dev/dm-0)
- centos7中的网卡名称相关知识
- What does /.autorelabel do when we reset the password in Red Hat?
- Reset lost root password
- How to Boot into Single User Mode in CentOS/RHEL 7
- Three Methods Boot CentOS/RHEL 7/8 Systems in Single User Mode
- CHAPTER 26. WORKING WITH GRUB 2
3 CentOS自定义发行版iso镜像制作
3.1 初次尝试制作镜像
在本小节,我们将iso镜像文件解压,然后将解压之后的文件原封不动地打成iso镜像,目的是为了熟悉镜像制作的各个命令行工具
为了减少环境因素对镜像制作造成的影响,这里使用docker容器来进行打包,DockerFile如下,非常简单,基础镜像为centos:7.6.1810
,并用yum安装了镜像制作的相关工具
1 | FROM centos:7.6.1810 |
接下来制作docker镜像
1 | docker build -t create-iso-env:1.0.0 . |
我们先研究一下官方的iso文件的结构,我下载的是CentOS-7-x86_64-Minimal-1908.iso
,解压之后,目录结构如下(rpm包太多了,这里省略掉)
1 | . |
运行docker。这里挂载了3个目录
/Users/hechenfeng/Desktop/source/CentOS-7-x86_64-Minimal-1908
:该目录是我解压iso文件之后得到的目录,对应于容器中的/source
目录/Users/hechenfeng/Desktop/workspace
:该目录是镜像制作的工作目录,对应于容器中的/workspace
目录/Users/hechenfeng/Desktop/iso
:该目录用于放置生成的iso文件,对应于容器中的/target
目录
1 | docker run \ |
以下命令均在容器中执行
第一步:将/source
目录中的内容,拷贝到/workspace
目录中
1 | # 删除除了. ..之外的所有文件以及目录,包括隐藏文件以及隐藏目录 |
第二步:根据comps.xml
制作本地repo。这里有一个坑,官方的CentOS镜像解压后,是不存在comps.xml
这个文件的,这个文件存在于repodata
目录中(容器中的路径为/workspace/repodata
),且名字是一个随机字符串。可以通过如下命令将该文件重命名且移动至上层目录,然后重新制作本地repo。此外,也可以从CentOS的官方文档中下载comps.xml
文件
1 | # 找到该comps.xml文件 |
第四步:接下来,就可以制作镜像了,详细流程可以参考RedHat文档
1 | fileName=/target/my-centos-1.iso |
3.2 修改发行版信息
我们重新运行一个容器来制作镜像
1 | docker run \ |
以下命令均在容器中执行
第一步:将/source
目录中的内容,拷贝到/workspace
目录中
1 | # 删除除了. ..之外的所有文件以及目录,包括隐藏文件以及隐藏目录 |
第二步:修改标签以及标题
1 | originalLabelEscape="CentOS\\\\x207\\\\x20x86_64" |
第三步:根据comps.xml
制作本地repo
1 | # 找到该comps.xml文件 |
第四步:制作镜像
1 | fileName=/target/my-centos-2.iso |
3.3 使用kickstart定制化安装流程
在正常装机完成之后,会有一个/root/anaconda.ks
文件,其内容如下。我们的kickstart
文件可以参考这个文件的内容来编写
1 | #version=DEVEL |
我们重新运行一个容器来制作镜像
1 | docker run \ |
以下命令均在容器中执行
第一步:将/source
目录中的内容,拷贝到/workspace
目录中
1 | # 删除除了. ..之外的所有文件以及目录,包括隐藏文件以及隐藏目录 |
第二步:编写kickstart
文件,路径为/workspace/liuyehcf.ks
,相比于上面展示的/root/anaconda.ks
,改造点如下
- 禁用了root账号
- 增加了一个用户
liuyehcf
,其密码为!Abcd1234
,密文可以通过命令python3 -c 'import crypt; print(crypt.crypt("!Abcd1234", crypt.mksalt()))'
获取 - 禁用自动分区,注释掉
autopart --type=lvm
- 避免安装完成重启时,仍然从iso启动,增加
reboot --eject
- 第一个post,将iso中的
EFI
目录拷贝到操作系统中的/EFI
目录(可以是任意文件或目录,这里用EFI
来做示范)- 需要指定
--nochroot
参数 /run/install/repo
:iso的挂载点/mnt/sysimage
:操作系统根目录的挂载点
- 需要指定
- 第二个post,执行一些定制化的步骤,这里是写了一个文件,
/root/greet
1 | cat > /workspace/liuyehcf.ks << 'EOF' |
第三步:修改配置文件,关联这个kickstart
文件(/workspace/liuyehcf.ks
)
1 | # ks文件的路径,工作目录/workspace,对iso来说就是根目录 |
第四步:根据comps.xml
制作本地repo
1 | # 找到该comps.xml文件 |
第五步:制作镜像
1 | fileName=/target/my-centos-3.iso |
验证
- 装机的时候,只需要进行一步操作,磁盘分区,其他操作都是自动进行的
- 用
liuyehcf/!Abcd1234
登录 - 检查
/EFI
目录以及子文件子目录是否存在 - 检查
root/greet
文件是否存在
3.4 Preboot Execution Environment, PXE
PXE安装的核心流程,下面拆分了DHCP Server
、PXE Server
、ISO Server
,在实际情况中,这三者通常来说是同一个服务器
下面以一个简单的例子来演示一下如何搭建PXE环境,在示例中DHCP Server
、PXE Server
、ISO Server
是同一台服务器。此外PXE
有四种启动模式,分别为IPV4 legacy
,IPV4 UEFI
,IPV6 legacy
,IPV6 UEFI
,这里主要介绍IPV4 legacy
启动模式需要的文件
3.4.1 预备工作
- 操作系统,我用的是
CentOS 7.6
- iso文件,我用的是
CentOS-7-x86_64-Minimal-1908.iso
- 安装
dhcpd
yum install -y dhcp
- 安装
tftp
yum install -y tftp-server
- 安装
ftp
/http
、nfs
中的任意一种,这里我选用ftpyum install -y vsftpd
3.4.2 配置并启动dhcp服务
1 | # 备份 |
allow booting
:允许客户端在booting
阶段查询host declaration
allow bootp
:允许对bootp query
做出响应PXE
相关配置PXE Server
的ip是192.168.66.1
- 启动引导器的文件名是
pxelinux.0
DHCP
相关配置DHCP Server
的ip是192.168.66.1
- 广播地址是
192.168.66.255
- 可分配的IP范围是
192.168.66.2
到192.168.66.254
3.4.3 配置并启动tftp服务
1 | # 清理tftp目录 |
3.4.4 配置并启动ftp服务
1 | # 清理ftp目录 |
3.4.5 编写pxelinux.cfg/default文件
1 | # 清理 |
3.4.6 编写kickstart文件
1 | cat > /var/ftp/iso/ks.cfg << 'EOF' |
- 配置从网络安装:
url --url="ftp://192.168.66.1/iso"
- 镜像中的其他目录,可以在post阶段通过wget进行下载
3.4.7 关闭防火墙
关掉防火墙,避免dhcp
、tftp
、ftp
、http
等服务无法访问
1 | systemctl disable firewalld |
3.4.8 配置从网络启动
BIOS配置(仅供参考,不同机器的BIOS菜单可能差异很大)
NO Disk(PXE)
:改为enableCSM Configuration
:Boot option filter
:UEFI and Legacy
Network
:LegacyStorage
:LegacyVideo
:LegacyOther PCI devices
:Legacy
3.5 其他
3.5.1 iso包含大文件(4G以上)
用genisoimage
制作iso的时候,如果包含了超过4G的文件,那么需要加上参数-allow-limited-size
。但是,这样会造成一个问题:如果iso中的某些文件在kickstart中会拷贝到目标的操作系统当中,那么这些文件的执行权限会丢失
如果包含了4G以上的文件,那就无法使用FAT32文件系统来制作U盘启动盘。但是我们可以使用split
以及cat
命令来拆分以及重建大文件,如此一来就又可以使用FAT32文件系统了
1 | # 拆分 |
3.5.2 下载某个软件的rpm包
针对当前环境,下载缺失的rpm包:yum install --downloadonly --downloaddir=<downloadDir> <app1> <app2> ...
yum install --downloadonly --downloaddir=/rpm gcc
下载所有的rpm包(无论当前系统是否存在):repotrack -a x86_64 -p <downloadDir> <app1> <app2> ...
repotrack -a x86_64 -p /rpm/ gcc wget
安装rpm包并解决冲突:rpm -ivh --replacepkgs --upgrade=*.rpm <directory>/*.rpm
rpm -ivh --replacepkgs --upgrade=*.rpm /rpm/*.rpm
3.5.3 安装时如何切换tty
- 从图形化界面切换到tty:
ctrl+alt+f<n>
,n可以是1-5 - 从tty切换到图形化界面:
ctrl+alt+f6
3.5.4 查找官方iso中的comps.xml文件
- 在
CentOS 7.6.1810
以及CentOS 7.7.1908
中,该xml都存在于repodata
目录中,只是名字是个随机串 - 在
CentOS 7.8.2003
中,该xml以压缩包的形式存在于repodata
目录中,压缩包的名字也是个随机串
3.5.5 kickstart语法
3.5.5.1 %packages
%packages
用于指定安装包(rpm包),在CentOS-7-x86_64-DVD-xxx/repodata
目录下,有个comps.xml
文件,该文件内有包含environment
、group
等的定义,可以用<environment>
以及<group>
来搜索相关的定义
指定environment
1 | %packages |
指定group
1 | %packages |
指定独立的rpm包,支持通配符
1 | %packages |
排除指定的environment
、group
以及独立的rpm包
1 | %packages |
3.6 参考
- 使用isolinux制作liveUSB
- CentOS Composer
- 按部就班—半自动化系统安装
- mkisofs制作镜像文件
- Building a Custom Boot ISO for Red Hat Virtualization Hypervisor
- How to use and edit comps.xml for package groups
- 定制自己的CentOS发行版
- CentOS官方comps.xml文件
- 使用ISOLinux制作Linux系统安装盘
- CentOS Kickstart 官方文档
- Red Hat Kickstart 官方文档
- Anaconda kickstart 官方文档
- Anaconda kickstart and rootpw option
- kickstart 中文文档
- Kickstart详解(转载)
- CentOS/RHEL 7 LVM Partitioning in Kickstart?
- PXE Network Boot Server
- PXE的部署过程
- PXE自动化系统安装服务器(DHCP + TFTP + syslinux +vsftpd)
- dhcp、tftp及pxe简介
- Linux-pxe~install网络安装
- Computer says “succeed to download nbp file” but doesn’t boot into PE
- how to make the first disk /dev/sda always
- Download all dependencies with yumdownloader, even if already installed?
4 核心概念
4.1 BIOS与UEFI
BIOS(Basic Input Output System)
是基本输入输出系统。它是一组固化到计算机内主板上一个ROM
芯片上的程序,保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,它可从CMOS
中读写系统设置的具体信息
UEFI(Unified Extensible Firmware Interface)
是统一可扩展固件界面,用来定义操作系统与系统硬件之间的软件界面,作为BIOS的替代方案。可扩展固件接口负责加电自检(POST),联系操作系统以及提供连接作业系统与硬体的介面
实际上PC的启动固件的引导流程从IBM PC机诞生第一天起,就没有本质改变过,无论传统BIOS还是UEFI,阳光之下没有什么新鲜的东西,启动本身无外乎三个步骤
Rom Stage
:在这个阶段没有内存,需要在ROM
上运行代码。这时因为没有内存,没有C语言运行需要的栈空间,开始往往是汇编语言,直接在ROM
空间上运行。在找到个临时空间(Cache
空间用作RAM
,Cache As Ram, CAR
)后,C语言终于可以粉墨登场了,后期用C语言初始化内存和为这个目的需要做的一切服务Ram Stage
:在经过ROM
阶段的困难情况后,我们终于有了可以大展拳脚的内存,很多额外需要大内存的东西可以开始运行了。在这时我们开始进行初始化芯片组、CPU、主板模块等等核心过程Find something to boot Stage
:终于要进入正题了,需要启动,我们找到启动设备。就要枚举设备,发现启动设备,并把启动设备之前需要依赖的节点统统打通。然后开始移交工作,Windows或者Linux的时代开始
传统BIOS尽管开始全部用汇编语言完成,但后期也部分引入了C语言,这些步骤完全是一样的。什么MBR
分区啊,UEFI
分区都是枝节问题,都是技术上可以做到的,没有什么是UEFI
可以做,传统BIOS不可以做到的。那既然有BIOS了,为什么还需要UEFI呢
- 传统
BIOS
来自于IBM,之后就进入战国时代,激烈的商战让接口统一成为了不可能做到的事,只有在面对微软这个大用户的时候,才勉强提供了兼容
的基于软中断的接口。它封闭、神秘和充满各种不清不楚的预设和祖传代码,在调试PCI
的ROM
时要小心各种ROM
之间互相踩,各种只有老师傅才知道的神奇诀窍
。要写个驱动,让它在各个BIOS厂商那里都能跑,简直成为了一件不可能完成的任务 - 由Intel推动,在一开始就将标准公开,拉上了微软这个PC界的霸主,强势统一了江湖。在近20年的深耕下,统一了固件启动阶段基础框架
Spec:PI Spec
与操作系统的接口Spec:UEFI Spec
,并将抽象硬件的原语性Spec: ACPI Spec
也拉入这个大家庭,都变成UEFI Forum
的一份子 - 现在只要符合
UEFI driver model
的驱动都可以在各个BIOS
上运行,打通了各个BIOS
厂商之间的栅栏;与此同时,符合UEFI
标准的操作系统都可以流畅的在各种主板上运行,无论是Windows
,还是Linux
各种发行版,甚至是Android
。实际上,PC生态圈的繁荣,和UEFI
的推广和被广泛接受是分不开的。值得一提的是UEFI
内核的大部分代码是由Intel的中国工程师开发的。在大家一次次电脑的正常运行后面,有他们辛勤工作背影。他们也为固件的开源和国产化做出了自己的贡献。代码已经全部开源一部分时间了
CSM Configuration(Compatibility Support Module)
(兼容性支持模块)是BIOS
上Boot
选项里的一个下拉子项目(一些老的主板上没有此选项),与Secure Boot
(安全启动,仅适用于使用UEFI启动的操作系统)是并列项。CSM
开启使得可以支持UEFI
启动和非UEFI
启动
- 若是需要启动传统
MBR
设备,则需开启CSM
,关闭Secure Boot
- 若是需要启动
UEFI
设备,则需要关闭CSM
,开启Secure Boot
4.2 Grub
GRUB
的作用有以下几个:
- 加载操作系统的内核
- 拥有一个可以让用户选择的的菜单,来选择到底启动哪个系统
- 可以调用其他的启动引导程序,来实现多系统引导
按照启动流程,BIOS
在自检完成后,会到第一个启动设备的MBR
中读取GRUB
。在MBR
中用来放置启动引导程序的空间只有446
Byte,那么GRUB
可以放到这里吗?答案是空间不够,GRUB
的功能非常强大,MBR
空间是不够使用的。那么Linux
的解决办法是把GRUB
的程序分成了三个阶段来执行
Stage 1
:执行GRUB
主程序:第一阶段是用来执行GRUB
主程序的,这个主程序必须放在启动区中(也就是MBR
或者引导扇区中)。但是MBR
太小了,所以只能安装GRUB
的最小的主程序,而不能安装GRUB
的相关配置文件。这个主程序主要是用来启动Stage 1.5
和Stage 2
的。Stage 1.5
:识别不同的文件系统:Stage 2
比较大,只能放在文件系统中(分区),但是Stage 1
不能识别不同的文件系统,所以不能直接加载Stage 2
。这时需要先加载Stage 1.5
,由Stage 1.5
来加载不同文件系统中的Stage 2
- 还有一个问题,难道
Stage 1.5
不是放在文件系统中的吗?如果是,那么Stage 1
同样不能找到Stage 1.5
。其实,Stage 1.5
还真没有放在文件系统中,而是在安装GRUB
时,直接安装到紧跟MBR
之后的32KB
的空间中,这段硬盘空间是空白无用的,而且是没有文件系统的,所以Stage 1
可以直接读取Stage 1.5
。读取了Stage 1.5
就能识别不同的文件系统,才能加载Stage 2
- 还有一个问题,难道
Stage 2
:加载GRUB
的配置文件:Stage 2
阶段主要就是加载GRUB
的配置文件/boot/grub/grub.conf
,然后根据配置文件中的定义,加载内核和虚拟文件系统。接下来内核就可以接管启动过程,继续自检与加载硬件模块了
4.3 Grub2
系统启动流程
- 加载
BIOS
的硬件信息与进行自检,并依据设置取得第一个可启动的设备(硬盘,光盘,U盘) - 读取并执行第一个启动设备内
MBR
(主引导分区)的boot loader
(如grub2
)- 严格意义上,
MBR
就是grub2
中的boot.img
,boot.img
的唯一作用就是读取core.img
的第一个扇区并跳转到它身上,将控制权交给该扇区的img
。由于体积原因,boot.img
是无法理解文件系统的,因此core.img
的位置是以硬编码的方式记录在boot.img
中的 core.img
加载启动菜单、加载目标操作系统的信息等
- 严格意义上,
- 依据
grub2
的设置加载Kernel
,Kernel
会开始检测硬件与加载驱动程序 - 在硬件驱动成功后,
Kernel
会主动调用systemd
进程(原来的init
进程),并以default.targert
流程开机
4.3.1 基础内容
4.3.1.1 grub2和grub的区别
- 配置文件的名称改变了。在
grub
中,配置文件为grub.conf
或menu.lst
(grub.conf
的一个软链接),在grub2中改名为grub.cfg
grub2
增添了许多语法,更接近于脚本语言了,例如支持变量、条件判断、循环grub2
中,设备分区名称从1
开始,而在grub
中是从0
开始的。grub2
使用img
文件,不再使用grub
中的stage1
、stage1.5
和stage2
- 支持图形界面配置grub,但要安装grub-customizer包,epel源提供该包。
- 在已进入操作系统环境下,不再提供
grub
命令,也就是不能进入grub
交互式界面,只有在开机时才能进入,算是一大缺憾。 - 在
grub2
中没有了好用的find
命令,算是另一大缺憾。
4.3.1.2 命名习惯和文件路径表示方式
(fd0)
:表示第一块软盘(hd0,msdos2)
:表示第一块硬盘的第二个mbr
分区。grub2
中分区从1
开始编号,传统的grub
是从0
开始编号的(hd0,msdos5)
:表示第一块硬盘的第一个逻辑分区(hd0,gpt1)
:表示第一块硬盘的第一个gpt
分区/vmlinuz
:相对路径,表示根设备下的vmlinuz
文件(hd0,msdos1)/vmlinuz
:绝对路径,表示第一硬盘第一分区下的vmlinuz
文件
4.3.1.3 grub2引导操作系统的方式
grub2
支持两种方式引导操作系统:
- 直接引导:
(direct-load)
直接通过默认的grub2 boot loader
来引导写在默认配置文件中的操作系统 - 链式引导:
(chain-load)
使用默认grub2 boot loader
链式引导另一个boot loader
,该boot loader
将引导对应的操作系统
- 一般只使用第一种方式,只有想引导grub默认不支持的操作系统时才会使用第二种方式。比如安装了
Windows
和Linux
双系统时,系统的boot loader
是grub2
,但是grub2
并不能引导启动Windows
,所以需要将执行权转交给Widnwos
系统分区的boot loader
4.3.1.4 文件分布
grub
的配置文件放置位置为/boot/grub/
,在grub2
中,这些文件被分别放置到如下位置中
/boot/grub/grub.cfg
:/etc/grub.d/
:放置grub
脚本的位置,这些脚本用于构建grub.cfg
/etc/default/grub
:这个文件包含grub
的基础配置,这些配置在构建grub.cfg
时,会被脚本读取
接下来介绍一下grub
脚本,脚本名称前面的数字代表了脚本执行的先后顺序
00_header
:该脚本用于读取grub
的基础配置/etc/default/grub
,包括超时等等10_linux
:该脚本用于加载发行版的菜单项30_os-prober
:该脚本用于扫描硬盘上其他操作系统并将其添加到启动菜单40_custom
:是一个模板,可用于创建要添加到启动菜单的其他条目
如何构建新的grub.cfg文件
CentOS
:grub2-mkconfig –o /boot/grub2/grub.cfg
,不加-o
参数会直接以标准输出的方式打印到屏幕上Ubuntu
:update-grub
grub.cfg
文件位置
CentOS
:/boot/efi/EFI/centos/grub.cfg
或者/boot/grub2/grub.cfg
Ubuntu
:/boot/grub/grub.cfg
4.3.1.5 boot loader和grub的关系
当使用grub
来管理启动菜单时,那么boot loader
都是grub
程序安装的。
传统的grub
将Stage 1
转换后的内容安装到MBR
(VBR
或EBR
)中的boot loader
部分,将Stage 1.5
转换后的内容安装在紧跟在MBR
后的扇区中,将Stage 2
转换后的内容安装在/boot
分区中。
grub2
将boot.img
转换后的内容安装到MBR
(VBR
或EBR
)中的boot loader
部分,将diskboot.img
和kernel.img
结合成为core.img
,同时还会嵌入一些模块或加载模块的代码到core.img
中,然后将core.img
转换后的内容安装到磁盘的指定位置处
4.3.1.6 grub2的安装位置
严格地说是core.img
的安装位置,因为boot.img
的位置是固定在MBR
或VBR
或EBR
上的
MBR
MBR
格式的分区表用于PC BIOS
平台,这种格式允许四个主分区和额外的逻辑分区。使用这种格式的分区表,有两种方式安装grub
:
- 嵌入到
MBR
和第一个分区中间的空间,这部分就是大众所称的boot track
,MBR gap
或embedding area
,它们大致需要31kB的空间- 使用嵌入的方式安装
grub
,就没有保留的空闲空间来保证安全性,例如有些专门的软件就是使用这段空间来实现许可限制的;另外分区的时候,虽然会在MBR和第一个分区中间留下空闲空间,但可能留下的空间会比这更小
- 使用嵌入的方式安装
- 将
core.img
安装到某个文件系统中,然后使用分区的第一个扇区(严格地说不是第一个扇区,而是第一个block
)存储启动它的代码- 方法二安装
grub
到文件系统,但这样的grub
是脆弱的。例如,文件系统的某些特性需要做尾部包装,甚至某些fsck
检测,它们可能会移动这些block
- 方法二安装
grub
开发团队建议将grub
嵌入到MBR
和第一个分区之间,除非有特殊需求,但仍必须要保证第一个分区至少是从第31kB(第63个扇区)之后才开始创建的- 现在的磁盘设备,一般都会有分区边界对齐的性能优化提醒,所以第一个分区可能会自动从第1MB处开始创建
gpt
- 一些新的系统使用
GUID
分区表(GPT)格式,这种格式是EFI
固件所指定的一部分。但如果操作系统支持的话,gpt
也可以用于BIOS
平台(即MBR
风格结合gpt
格式的磁盘),使用这种格式,需要使用独立的BIOS boot
分区来保存grub
,grub
被嵌入到此分区,不会有任何风险 - 当在
gpt
磁盘上创建一个BIOS boot
分区时,需要保证两件事- 它最小是31kB大小,但一般都会为此分区划分1MB的空间用于可扩展性
- 必须要有合理的分区类型标识(flag type)
gun parted
工具可以设置bios_grub
标识- 如果使用
gdisk
分区工具时,则分类类型设置为EF02
4.3.1.7 进入grub命令行
在传统的grub
上,可以直接在bash
下敲入grub
命令进入命令交互模式,但grub2
只能在系统启动前进入grub
交互命令行
按下e
见可以编辑所选菜单对应的grub
菜单配置项,按下c
键可以进入grub
命令行交互模式
4.3.2 安装grub2
这里的安装指的不是安装grub
程序,而是安装Boot loader
,但一般都称之为安装grub
,且后文都是这个意思
4.3.2.1 grub安装命令
安装方式非常简单,只需调用grub2-install
,然后给定安装到的设备名即可
1 | grub2-install /dev/sda |
这样的安装方式,默认会将img
文件放入到/boot
目录下,如果想自定义放置位置,则使用--boot-directory
选项指定,可用于测试练习grub
的时候使用,但在真实的grub
环境下不建议做任何改动
1 | grub2-install --boot-director=/mnt/boot /dev/fd0 |
如果是EFI
固件平台,则必须挂载好efi
系统分区,一般会挂在/boot/efi
下,这是默认的,此时可直接使用grub2-install
安装
1 | grub2-install |
如果不是挂载在/boot/efi
下,则使用--efi-directory
指定efi
系统分区路径
1 | grub2-install --efi-directory=/mnt/efi |
4.3.2.2 各种img和stage文件的说明
img
文件是grub2
生成的,stage
文件是传统grub
生成的。下面是各种文件的说明
4.3.2.2.1 grub2中的img文件
grub2
生成了好几个img
文件,有些分布在/usr/lib/grub/i386-pc
目录下,有些分布在/boot/grub2/i386-pc
目录
下图描述了各个img
文件之间的关系。其中core.img
是动态生成的,路径为/boot/grub2/i386-pc/core.img
,而其他的img
则存在于/usr/lib/grub/i386-pc
目录下。当然,在安装grub
时,boot.img
会被拷贝到/boot/grub2/i386-pc
目录下
boot.img
- 在
BIOS
平台下,boot.img
是grub
启动的第一个img
文件,它被写入到MBR
中或分区的boot sector
中,因为boot sector
的大小是512
字节,所以该img
文件的大小也是512
字节 boot.img
唯一的作用是读取属于core.img
的第一个扇区并跳转到它身上,将控制权交给该扇区的img
。由于体积大小的限制,boot.img
无法理解文件系统的结构,因此grub2-install
将会把core.img
的位置硬编码到boot.img
中,这样就一定能找到core.img
的位置
- 在
core.img
core.img
根据diskboot.img
、kernel.img
和一系列的模块被grub2-mkimage
程序动态创建。core.img
中嵌入了足够多的功能模块以保证grub
能访问/boot/grub
,并且可以加载相关的模块实现相关的功能,例如加载启动菜单、加载目标操作系统的信息等,由于grub2
大量使用了动态功能模块,使得core.img
体积变得足够小core.img
中包含了多个img
文件的内容,包括diskboot.img
、kernel.img
等core.img
的安装位置随MBR
磁盘和GPT
磁盘而不同
diskboot.img
- 如果启动设备是硬盘,即从硬盘启动时,
core.img
中的第一个扇区的内容就是diskboot.img
。diskboot.img
的作用是读取core.img
中剩余的部分到内存中,并将控制权交给kernel.img
,由于此时还不识别文件系统,所以将core.img
的全部位置以block列表的方式编码,使得diskboot.img
能够找到剩余的内容。 - 该
img
文件因为占用一个扇区,所以体积为512字节
- 如果启动设备是硬盘,即从硬盘启动时,
cdboot.img
- 如果启动设备是光驱(
cd-rom
),即从光驱启动时,core.img
中的第一个扇区的的内容就是cdboo.img
。它的作用和diskboot.img
是一样的
- 如果启动设备是光驱(
pexboot.img
- 如果是从网络的PXE环境启动,
core.img
中的第一个扇区的内容就是pxeboot.img
。
- 如果是从网络的PXE环境启动,
kernel.img
kernel.img
文件包含了grub
的基本运行时环境:设备框架、文件句柄、环境变量、救援模式下的命令行解析器等等。很少直接使用它,因为它们已经整个嵌入到了core.img
中了。注意,kernel.img
是grub
的kernel
,和操作系统的内核无关- 如果细心的话,会发现
kernel.img
本身就占用28KB空间,但嵌入到了core.img
中后,core.img
文件才只有26KB大小。这是因为core.img
中的kernel.img
是被压缩过的
lnxboot.img
- 该
img
文件放在core.img
的最前部位,使得grub
像是linux
的内核一样,这样core.img
就可以被LILO的image=
识别。当然,这是配合LILO来使用的,但现在谁还适用LILO呢
- 该
*.mod
- 各种功能模块,部分模块已经嵌入到
core.img
中,或者会被grub
自动加载,但有时也需要使用insmod
命令手动加载
- 各种功能模块,部分模块已经嵌入到
4.3.2.2.2 传统grub中的stage文件
grub2
的设计方式和传统grub
大不相同,因此和stage
之间的对比关系其实没那么标准,但是将它们拿来比较也有助于理解img
和stage
文件的作用。
stage
文件也分布在两个地方:/usr/share/grub/RELEASE
目录下和/boot/grub
目录下,/boot/grub
目录下的stage
文件是安装grub
时从/usr/share/grub/RELEASE
目录下拷贝过来的
stage1
stage1
文件在功能上等价于boot.img
文件。目的是跳转到stage1_5
或stage2
的第一个扇区上
*_stage1_5
*stage1_5
文件包含了各种识别文件系统的代码,使得grub
可以从文件系统中读取体积更大功能更复杂的stage2
文件。从这一方面考虑,它类似于core.img
中加载对应文件系统模块的代码部分,但是core.img
的功能远比stage1_5
多stage1_5
一般安装在MBR
后、第一个分区前的那段空闲空间中,也就是MBR gap
空间,它的作用是跳转到stage2
的第一个扇区。- 其实传统的
grub
在某些环境下是可以不用stage1_5
文件就能正常运行的,但是grub2
则不能缺少core.img
stage2
stage2
的作用是加载各种环境和加载内核,在grub2
中没有完全与之相对应的img
文件,但是core.img
中包含了stage2
的所有功能- 当跳转到
stage2
的第一个扇区后,该扇区的代码负责加载stage2
剩余的内容 - 注意,
stage2
是存放在磁盘上的,并没有像core.img
一样嵌入到磁盘上
stage2_eltorito
- 功能上等价于
grub2
中的core.img
中的cdboot.img
部分。一般在制作救援模式的grub
时才会使用到cd-rom
相关文件
- 功能上等价于
pxegrub
- 功能上等价于
grub2
中的core.img
中的pxeboot.img
部分
- 功能上等价于
4.3.2.3 安装grub涉及的过程
安装grub2
的过程大体分两步:
- 一是根据
/usr/lib/grub/i386-pc/
目录下的文件生成core.img
,并拷贝boot.img
和core.img
涉及的某些模块文件到/boot/grub2/i386-pc/
目录下 - 二是根据
/boot/grub2/i386-pc
目录下的文件向磁盘上写boot loader
当然,到底是先拷贝,还是先写boot loader
,没必要去搞清楚,只要/boot/grub2/i386-pc
下的img
文件一定能通过grub2
相关程序再次生成boot loader
。所以,既可以认为/boot/grub2/i386-pc
目录下的img
文件是boot loader
的特殊备份文件,也可以认为是boot loader
的源文件
不过,img
文件和boot loader
的内容是不一致的,因为img
文件还要通过grub2
相关程序来转换才是真正的boot loader
对于传统的grub
而言,拷贝的不是img
文件,而是stage
文件。
4.3.3 命令行和菜单项中的命令
4.3.3.1 grub菜单
菜单格式如下
1 | menuentry <title> [--class=<class> ...] [--users=<users>] [--unrestricted] [--hotkey=<key>] [--id=<id>] { |
这是grub.cfg
中最重要的项。该命令定义了一个名为<title>
的grub
菜单项。执行顺序如下:
- 执行大括号中的命令列表
- 如果大括号中的命令全部执行成功,且成功加载了对应的内核,将执行
boot
命令(menuentry
都会在最后隐式携带一个boot
命令),随后grub
就将控制权交给了操作系统内核
4.3.3.2 命令
4.3.3.2.1 help命令
1 | help [pattern] |
显示能匹配到pattern
的所有命令的说明信息和usage
信息,如果不指定patttern
,将显示所有命令的简短信息
4.3.3.2.2 boot命令
boot
:用于启动已加载的操作系统
只在交互式命令行下可用。其实在menuentry
命令的结尾就隐含了boot
命令
4.3.3.2.3 set命令和unset命令
set
:设置环境变量的值,如果不给定参数,则列出当前环境变量unset
:释放环境变量的值
示例
1 | set [envvar=value] |
4.3.3.2.4 lsmod命令和insmod命令
lsmod
:列出已加载的模块insmod
:调用指定的模块
4.3.3.2.5 linux和linux16命令
1 | linux file [kernel_args] |
linux
/linux16
/linuxefi
:都表示装载指定的内核文件,并传递内核启动参数。linux16
表示以传统的16位启动协议启动内核,linux
表示以32
位启动协议启动内核,但linux
命令比linux16
有一些限制。但绝大多数时候,它们是可以通用的
在linux
或linux16
或linuxefi
命令之后,必须紧跟着使用initrd
或initrd16
或initrdefi
命令装载init ramdisk
文件
内核文件一般为/boot
分区下的vmlinuz-RELEASE_NUM
文件
在grub
环境下,boot
分区被当作root device
,即根设备,假如boot
分区为第一块磁盘的第一个分区,则应该写成
1 | linux (hd0,msdos1)/vmlinuz-XXX |
或者相对路径
1 | set root='hd0,msdos1' |
在grub阶段可以传递内核的启动参数(内核的参数包括3类:编译内核时参数,启动时参数和运行时参数),可以传递的启动参数非常非常多,完整的启动参数列表。这里只列出几个常用的
init=
:指定Linux启动的第一个进程init的替代程序root=
:指定根文件系统
所在分区,在grub中,该选项必须给定。另外,root启动参数有多种定义方式- 可以使用UUID的方式指定,例如
linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=edb1bf15-9590-4195-aa11-6dac45c7f6f3 ro rhgb quiet LANG=en_US.UTF-8
- 也可以直接指定根文件系统所在分区,如
linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=/dev/sda2 ro rhgb quiet LANG=en_US.UTF-8
- 可以使用UUID的方式指定,例如
ro,rw
:启动时,根分区以只读还是可读写方式挂载。不指定时默认为roinitrd
:指定init ramdisk
的路径。在grub中因为使用了initrd
或initrd16
命令,所以不需要指定该启动参数rhgb
:以图形界面方式启动系统quiet
:以文本方式启动系统,且禁止输出大多数的log messagenet.ifnames=0
:用于CentOS 7,禁止网络设备使用一致性命名方式biosdevname=0
:用于CentOS 7,也是禁止网络设备采用一致性命名方式。
- 只有
net.ifnames
和biosdevname
同时设置为0时,才能完全禁止一致性命名,得到eth0-N的设备名
4.3.3.2.6 initrd和initrd16命令
1 | initrd file |
只能紧跟在linux
或linux16
或linuxefi
命令之后使用,用于为即将启动的内核传递init ramdisk
路径
同样,基于根设备,可以使用绝对路径,也可以使用相对路径。路径的表示方法和linux
或linux16
或linuxefi
命令相同,例如
1 | linux16 /vmlinuz-0-rescue-d13bce5e247540a5b5886f2bf8aabb35 root=UUID=b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8 ro crashkernel=auto quiet |
4.3.3.2.7 search命令
1 | search [--file|--label|--fs-uuid] [--set [var]] [--no-floppy] [--hint args] name |
通过文件[--file]
、卷标[--label]
、文件系统UUID[--fs-uuid]
来搜索设备。
如果使用了--set
选项,则会将第一个找到的设备设置为环境变量var
的值,默认的变量var
为root
搜索时可使用--no-floppy
选项来禁止搜索软盘,因为软盘速度非常慢,已经被淘汰了
有时候还会指定--hint=XXX
,表示优先选择满足提示条件的设备,若指定了多个hint
条件,则优先匹配第一个hint
,然后匹配第二个,依次类推
1 | if [ x$feature_platform_search_hint = xy ]; then |
- 上述
if
语句中的第一个search
中搜索uuid为367d6a77-033b-4037-bbcb-416705ead095
的设备,但使用了多个hint
选项,表示先匹配bios
平台下/boot
分区为(hd0,msdos1)
的设备,之后还指定了几个hint
,但因为search
使用的是uuid
搜索方式,所以这些hint
选项是多余的,因为单磁盘上分区的uuid
是唯一的
再举个例子,如果某启动设备上有两个boot
分区(如多系统共存时),分别是(hd0,msdos1)
和(hd0,msdos5)
,如果此时不使用uuid
搜索,而是使用label
方式搜索
1 | search --no-floppy --fs-label=boot --set=root --hint=hd0,msdos5 |
4.3.3.3 几个常设置的内置变量
4.3.3.3.1 root变量
该变量指定根设备
的名称,使得后续使用从/
开始的相对路径引用文件时将从该root
变量指定的路径开始。一般该变量是grub
启动的时候由grub
根据prefix
变量设置而来的
例如,如果grub
安装在第一个硬盘的的第一个分区上,那么prefix
就是(hd0,msdos1)/boot/grub
;root
就是(hd0,msdos1)
注意:在Linux中,从根/
开始的路径表示绝对路径,如/etc/fstab
。但grub中,从/
开始的表示相对路径,其相对的基准是root
变量设置的值,而使用(dev_name)/
开始的路径才表示绝对路径
一般root
变量都表示/boot
所在的分区。但这不是绝对的,如果设置为根文件系统所在分区,如root=(hd0,gpt2)
,则后续可以使用/etc/fstab
来引用(hd0,gpt2)/etc/fstab
文件
另外,root
变量还应该于linux
或linux16
或linuxefi
命令所指定的内核启动参数root=
区分开来,内核启动参数中的root=
的意义是固定的,其指定的是根文件系统所在分区
。例如:
1 | set root='hd0,msdos1' |
一般情况下,/boot
都会单独分区,所以root
变量指定的根设备和root
启动参数所指定的根分区不是同一个分区,除非/boot不是单独的分区,而是在根分区下的一个目录
4.3.3.3.2 chosen变量
当开机时选中某个菜单项启动时,该菜单的title
将被赋值给chosen
变量。该变量一般只用于引用,而不用于修改
4.3.3.3.3 cmdpath变量
grub2
加载的core.img
的目录路径,是绝对路径,即包括了设备名的路径,如(hd0,gpt1)/boot/grub2/
。该变量值不应该修改
4.3.3.3.4 default
指定默认的菜单项,一般其后都会跟随timeout
变量
default
指定默认菜单时,可使用菜单的title
,也可以使用菜单的id
,或者数值顺序,当使用数值顺序指定default
时,从0开始计算
4.3.3.3.5 timeout变量
设置菜单等待超时时间,设置为0时将直接启动默认菜单项而不显示菜单,设置为-1
时将永久等待手动选择
4.3.3.3.6 fallback变量
当默认菜单项启动失败,则使用该变量指定的菜单项启动,指定方式同default
,可使用数值(从0开始计算)、title
或id
指定
4.3.3.3.7 grub_platform变量
指定该平台是pc
还是efi
,pc
表示的就是传统的bios
平台
该变量不应该被修改,而应该被引用,例如用于if判断语句中
4.3.3.3.8 prefix变量
在grub
启动的时候,grub
自动将/boot/grub2
目录的绝对路径赋值给该变量,使得以后可以直接从该变量所代表的目录下加载各文件或模块。
例如,可能自动设置为set prefix = (hd0,gpt1)/boot/grub2/
所以可以使用$prefix/grubN.cfg
来引用/boot/grub2/grubN.cfg
文件。
该变量不应该修改,且若手动设置,则必须设置正确,否则牵一发而动全身
4.4 重要文件介绍
4.4.1 vmlinuz
vmlinuz
是可引导的、压缩的内核。vm
代表Virtual Memory
。Linux支持虚拟内存,不像老的操作系统比如DOS有640KB内存的限制。Linux能够使用硬盘空间作为虚拟内存,因此得名vm
。vmlinuz
是可执行的Linux内核,路径为/boot/vmlinuz
(具体来说形如/boot/vmlinuz-3.10.0-957.el7.x86_64
)
4.4.2 initrd
initrd
是initial ramdisk
的简写。initrd
是在系统引导过程中挂载的一个临时根文件系统
,用来支持两阶段的引导过程。initrd
文件中包含了各种可执行程序和驱动程序,它们可以用来挂载实际的根文件系统(当挂载完真实的根文件系统之后,可以将这个initrd
卸载,并释放内存,在很多嵌入式Linux系统中,initrd
就是最终的根文件系统)
initrd
中包含了实现这个目标所需要的目录和可执行程序的最小集合,例如将内核模块加载到内核中所使用的insmod
工具
initrd
是什么文件系统?内核直接能识别这个文件系统吗?:initrd
的文件系统是ext2
,内核应该内置了ext2
的相关模块
4.4.2.1 initramfs
kernel 2.6
以来都是initramfs
了,只是很多还沿袭传统使用initrd
的名字
initramfs
的工作方式更加简单直接一些,启动的时候加载内核和initramfs
到内存执行,内核初始化之后,切换到用户态执行initramfs
的程序/脚本,加载需要的驱动模块、必要配置等,然后加载rootfs
切换到真正的rootfs
上去执行后续的init
过程。initrd
是kernel 2.4
及更早的用法(现在你能见到的initrd
文件实际差不多都是initramfs
了),运行过程大概是内核启动,执行一些initrd
的内容,加载模块啥的,然后交回控制权给内核,最后再切到用户态去运行用户态的启动流程
可以通过命令行工具lsinitrd
查看initramfs
的内容
1 | lsinitrd |
4.5 参考
- UEFI 引导与 BIOS 引导在原理上有什么区别?
- How to make Windows 7 USB flash install media from Linux?
- 详解uefi、legacy以及U盘格式对系统安装的影响
- MBR与GPT
- 聊聊BIOS、UEFI、MBR、GPT、GRUB
- GRUB bootloader - Full tutorial
- GRUB 2 bootloader - Full tutorial
- GRUB 官方文档(简体中文)
- grub2详解(翻译和整理官方手册)
- GRUB2配置文件"grub.cfg"详解(GRUB2实战手册)
- GRUB legacy和GRUB 2介绍 与 命令【包含kernel 与 initrd的详解】使用
- Linux启动引导程序(GRUB)加载内核的过程
- GRUB入门教程
- What exactly is GRUB?
- 你知道计算机启动过程吗?
- 系统启动流程
- UEFI启动和Bios(Legacy)启动的区别
- Linux initial RAM disk (initrd) overview
- Initramfs/指南
- 浅谈linux启动的那些事(initrd.img)
- boot分区-百度百科
- initrd-百度百科
- grub Kernel_parameters
- grub Kernel_parameters(极详细)
- 启动流程、模块管理、BootLoader(Grub2)
- What on earth is Dracut?
- initrd和initramfs的区别是什么?
- The difference between initrd and initramfs?
- Initramfs 原理和实践
5 Ubuntu装机
博主安装的是server版本
- 设置root密码:
sudo passwd root
- 网卡配置文件为
/etc/network/interfaces
(无需修改) - 安装openssh:
apt-get install -y openssh-server
- 修改ssh配置文件
/etc/ssh/sshd_config
,将PermitRootLogin
改为yes
,重启sshd:service ssh restart
6 Ubuntu自定义发行版iso镜像制作
6.1 初次尝试制作镜像
在本小节,我们将iso镜像文件解压,然后将解压之后的文件原封不动地打成iso镜像,目的是为了熟悉镜像制作的各个命令行工具
为了减少环境因素对镜像制作造成的影响,这里使用docker容器来进行打包,DockerFile如下,非常简单,基础镜像为centos:7.6.1810
,并用yum安装了镜像制作的相关工具
1 | FROM centos:7.6.1810 |
接下来制作docker镜像
1 | docker build -t create-iso-env:1.0.0 . |
运行docker。这里挂载了3个目录
/Users/hechenfeng/Desktop/source/ubuntu-18.04.4-live-server-amd64
:该目录是我解压iso文件之后得到的目录,对应于容器中的/source
目录/Users/hechenfeng/Desktop/workspace
:该目录是镜像制作的工作目录,对应于容器中的/workspace
目录/Users/hechenfeng/Desktop/iso
:该目录用于放置生成的iso文件,对应于容器中的/target
目录
1 | docker run \ |
以下命令均在容器中执行
第一步:将/source
目录中的内容,拷贝到/workspace
目录中
1 | # 删除除了. ..之外的所有文件以及目录,包括隐藏文件以及隐藏目录 |
第二步:接下来,就可以制作镜像了
1 | fileName=/target/my-ubuntu-1.iso |
6.2 使用kickstart定制化安装流程
我们重新运行一个容器来制作镜像,这里使用另一个iso(ubuntu-18.04.4-desktop-amd64.iso
)来示范
1 | docker run \ |
以下命令均在容器中执行
第一步:将/source
目录中的内容,拷贝到/workspace
目录中
- 注意,拷贝时要用
cp -vrf /source/. /workspace/
,而不是cp -vrf /source/* /workspace/
,因为/source
目录下存在一个隐藏文件夹.disk
,如果该文件夹丢失的话,做出来的iso在装机阶段会出现unable to find a medium containing a live file system
1 | # 删除除了. ..之外的所有文件以及目录,包括隐藏文件以及隐藏目录 |
第二步:编写preseed.cfg
文件,路径为/workspace/preseed.cfg
- 如何生成加密的密码
openssl passwd -crypt <my password>
perl -e "print crypt('<my password>','sa');"
ruby -e 'print "<my password>".crypt("JU"); print("\n");'
php -r "print(crypt('<my password>','JU') . \"\n\");"
python -c 'import crypt; print crypt.crypt("<my password>","Fx")'
1 | cat > /workspace/preseed.cfg << 'EOF' |
第三步:修改grub配置文件/workspace/isolinux/txt.cfg
,关联这个kickstart
文件(/workspace/preseed.cfg
)
1 | mv /workspace/isolinux/txt.cfg /workspace/isolinux/txt.cfg.bak |
第四步:接下来,就可以制作镜像了
1 | fileName=/target/my-ubuntu-2.iso |
6.3 其他
6.3.1 确定目标磁盘挂载点
如何确定目标磁盘的挂载点:mount | grep <硬盘盘符>
,例如mount | grep sda
6.3.2 下载某个软件的deb包1
我们可以通过apt install -d <name>
来下载某个软件及其所有依赖的deb包。deb包的下载目录是:/var/cache/apt/archives
6.3.3 下载某个软件的deb包2
我们可以通过apt-get download <name>
来下载软件包,但是该命令只会下载指定的软件包,而不会下载依赖以及依赖的依赖
我们如何确定一个软件包以及所有依赖?可以借助工具apt-rdepends
1 | # 安装apt-rdepends |
下载完成后,可以通过dpkg -i *.deb
来进行软件安装
我们可以借助下面的脚本来完成依赖分析以及下载
1 | cat > ~/download.sh << 'EOF' |
6.3.4 允许root登录图形化界面
step1:编辑/usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf
文件,改成如下内容:
1 | [Seat:*] |
step2:编辑/etc/pam.d/gdm-autologin
文件,注释掉如下行(大约是第三行):
1 | #auth required pam_succeed_if.so user != root quiet_success |
step3:编辑/etc/pam.d/gdm-password
文件,注释掉如下行(大约是第三行):
1 | #auth required pam_succeed_if.so user != root quiet_success |
step4:编辑/root/.profile
,修改成如下内容:
1 | # ~/.profile: executed by Bourne-compatible login shells. |
step5:重启生效配置
6.4 参考
- Automatic Installation
- Appendix B. Automating the installation using preseeding
- ubuntu preseed无人应答安装
- preseed 示例
- 定制ubuntu发行版
- 如何创建完全无人值守的Ubuntu Desktop 16.04.1 LTS安装?
- 如何创建完全无人值守的Ubuntu安装?
- ubuntu安装光盘iso修改方法总结
- InstallCDCustomization
- 定制ubuntu镜像
- XPS 9560 cannot install Ubuntu. ACPI Error / Empty Installation type / "unable to find a medium containing a live file system”
- debian软件包下载站
- ubuntu安装/查看已安装包的方法
7 其他常见问题
7.1 查看版本号
lsb_release -a
:yum install -y redhat-lsb
uname -r
:内核版本号/etc/*-release
,包括/etc/os-release
/etc/centos-release
/etc/debian_version
/proc/version
7.2 制作U盘启动盘
7.2.1 MacOS
1 | # 先列出所有设备 |
7.2.2 Linux
1 | # 先列出所有设备 |
7.3 安装图形化界面
如果你的CentOS
是最小化安装的那默认都是不带X WINDOWS
的,所以在安装这些桌面之前得先安装一下X WINDOWS
,这个控制功能
1 | yum -y groupinstall "X Window System" |
7.3.1 安装GNOME
1 | yum -y groups install "GNOME Desktop" |