文件系统
块设备命名:
IDE设备:/dev/hda, /dev/hdb
SATA/SAS/USB设备:/dev/sda, /dev/sdb
virtio-blk 超虚拟化存储: /dev/vda, /dev/vdb
NVMe设备(SSD):/dev/nvme0, /dev/nvme1
逻辑卷:/dev/mapper/*
文件系统类型:
Windows 文件系统类型: fat32, NTFS
Linux 本地文件系统: ext2, ext3, ext4(rhel6), xfs(rhel7, rhel8)
网络文件系统: NFS, CIFS
集群文件系统: GFS, GFS2
分布式文件系统: CEPH
光盘: iso9660
文件数据块(block):存放文件的数据,文件的最小存储单元,默认大小是 4K。
inode 是文件的唯一标识号,存放文件的元数据,包括:
- 文件类型,权限,UID 和 GID
- 文件的链接数
- 文件大小和时间戳
- 文件数据块(block)在磁盘上的块指针
- 其他信息
使用 df -h
查看系统的文件组织结构
目录和文件的关系
系统识别文件是通过 inode
人识别文件是通过文件名
目录用来存放文件名和 inode 的映射关系,使用 ls -i file.sh
查看,可以得到 1075535 file.sh
文件:数据部分就是文件内容,元数据部分是文件属性
目录:数据部分是文件名和 inode 的对应关系,元数据部分是目录属性
cp 和 inode 的关系
- 分配一个新的 inode,并添加到 inode 表里
- 在新的目录下面,将该 inode 关联一个文件名
- 数据拷贝到新的文件
rm 和 inode 的关系
- 每执行一次 rm,链接数减1
- 当链接数变为 0 时,inode 会被回收,数据不会被擦除,只是标记为可用
mv 和 inode 的关系
在同一个文件系统内:
- 在新的目录下面创建文件名和 inode 的对应关系
- 删除旧目录下的对应关系
在不同的文件系统下:
cp + rm
硬链接
同一个文件系统下,多个文件名指向同一个 inode,这些文件的内容一样,修改其中的一个文件内容,其它的内容也会变。
语法:ln filename linkname
软链接
软链接和源文件有着不同的 inode,这是两个不同的文件。linkname 始终链接到 filename。
语法:ln -s filename linkname
如果用相对路径,这里的 filename 指的是相对于 linkname 的路径,所以 filename 最好用绝对路径。
tips: 软链接的大小,是源文件所在的位置,该位置的字符串的长度
文件类型
- 普通文件
d 目录
c 字符设备文件
b 块设备文件
l 链接文件
p 管道文件
s 套接字文件
文件系统使用情况
-
baobab 使用图形工具查看文件系统使用情况
-
df 查看已挂载的文件系统使用情况
-h 查看文件系统的使用情况,单位换算为 M 和 G 等
-i 查看 inode 使用情况
-T 查看文件系统类型 -
du 查看目录的大小
-h 查看文件系统的使用情况(以 block 为单位),单位换算为 M 和 G 等
-s 查看目录汇总的大小
文件压缩和打包
打包
打包把多个文件变成一个文件,不压缩数据,保留文件的属性,进行备份恢复时很方便。
tar 工具
tar [options] tarfile sourcefile
-c 建立归档
-f 指定归档名
-x 解包
-t 列出归档内容
-z 调用gzip压缩工具,进行归档压缩
-j 调用bzip2压缩工具,进行归档压缩
-J 调用xz压缩工具,进行归档压缩
-v 显示所有过程
-C 将文件解压到指定目录下
可以只解包一部分文件,方法是在后面指定
tar -zxf etc.tar.gz etc/hostname
压缩
将文件变小
gzip/gunzip filename,压缩成.gz
bzip2/bunzip2 filename,压缩成.bz
xz/unxz filename,压缩成.xz
三个压缩工具的压缩比依次增大
如果没有扩展名,使用 file 文件名
来查看文件的类型
挂载和卸载文件系统
mount
语法:mount 设备 挂载点
挂载光盘:mount /dev/cdrom /media
umount
语法:umount 设备/挂载点
umount /dev/cdrom
或者 umount /media
软件包
rpm
rpm: redhat package manager 红帽包管理器
vsftpd-3.0.3-28.el8.x86_64_.rpm
vsftpd: 软件包的名字
3.0.3: 软件包的开源版本号
28.el8: 红帽的发布版,编译版本
x86_64: 软件包运行的 CPU 架构
rpm -ivh vsftpd-3.0.3-28.el8.x86_64_.rpm 安装软件包
但 rpm 不能一并安装依赖的软件包,需要手动安装
yum 可以在安装的同时,安装依赖的软件包
yum
RHEL8 中 yum 现在对应的是 dnf 的命令。
仓库配置文件 /etc/yum.repos.d/*.repo
yum clean all 清除缓存
-
安装
yum install package 安装软件包
yum group install packagegroup 安装包组
yum reinstall package 重新安装软件包
yum local install packagelocation 安装软件包时,尝试从本地安装依赖包
-
移除
yum remove package 移除软件包
yum group remove packagegroup 移除包组
-
升级
yum update [package] 升级软件包
-
查询
yum repolist all 列出所有的仓库信息
yum list all 列出仓库里面所有的软件包
yum list installed 列出所有已安装的包
yum list available 列出所有未安装的包
yum install update 列出所有待更新的包
yum info package 查看软件包的信息
yum group info packagegroup 查看包组的信息
yum group list [hidden] 列出所有的包组
-
搜索文件和软件包
yum provides filename 查找文件来自哪个包
yum search keyword 查找与keyword相关的软件包
如果不小心删除了文件或者某个命令找不到,可以用 yum provides filename
找到该文件或命令是哪个软件包提供的,然后再 yum reinstall package
即可。
所有安装和删除事务的日志记录在 /var/log/dnf.rpm.log 中
- 历史记录
yum history 查询 yum 执行的历史记录
yum history list package 在历史记录中搜索某个包
yum history info 4 查询第4条历史记录的信息
yum history undo 7 撤销事务
创建私有 yum 源
-
将 rpm 包放在一个目录下面(例如放在
/data
下面) -
修改
/etc/yum.repos.d/rhel8.repo
,添加如下信息
1 | [data] |
- 使用 createrepo 命令在
/data
下面创建 repodata
yum install -y createrepo_c
createrepo -v /data
yum 的原理:yum 的信息来自于 repodata,真正安装的时候才用到 xxx.rpm 包
如果,将 xxx.rpm 放在 /data/Package 目录下,那么 createrepo 到底是要写成 createrepo -v /data
还是 createrepo -v /data/Package
呢?
答案是都可以。取决于你自己。如果是前者,那么 repodata 将会在 /data/repodata
,如果是后者,将会在 /data/Package/repodata
。
1 | yum install --downloadonly --downloaddir=/root ansible 只下载软件包,不安装 |
rpm 查询
rpm 没有仓库,不能查询哪些包没有安装
注意,使用 rpm -qp --sctipts vstpd-3.0.3-28.el8.x86_64.rpm
可以查看 rpm 包中的 shell 脚本
rpm 可以解压缩,使用
1 | rpm2cpio xxx.rpm | cpio -id |
会把包中的所有文件抽取出来,生成一个目录结构。如果你的文件之前不小心被误删,除了 reinstall 的方法,还可以用这种方法找到丢失的文件。
模块流
为了维护多个软件包的版本而存在
模块流由 AppStream 提供,BaseOS提供一些基础包。
列出维护的模块流: yum module list
,d 代表不指定版本号时默认会安装的版本,e 代表 enable,x 代表 disable
安装指定版本的:yum module install postgresql:9.6
移除:yum module remove postgresql
如果安装了 10 版本的 postgresql,想换成 9.6 版本的
切换模块流:
- 删除已经安装的
1 | yum module remove postgresql |
- 重置模块流
1 | yum module reset postgresql |
- 安装其他版本
1 | yum module install postgresql:9.6 |
yum install gcc gcc-c++ make unzip pcre pcre-devel zlib zlib-devel libxml2 libxml2-devel readline readline-devel ncurses ncurses-devel perl-devel perl-ExtUtils-Embed openssl-devel
编译安装
以 nginx 为例
下载好源码包之后
1 | ./configure --prefix=/usr/local/nginx --with-http_ssl_module |
nginx 服务管理
1 | /usr/local/nginx/sbin/nginx 启动服务 |
服务管理和系统启动流程
管理服务
之前管理服务是通过脚本,现在由 systemctl 来统一管理(但实际上还是调用脚本)。
vsftpd,httpd,systemd,其中的 d 是 dameon,守护进程的意思。
在红帽中,第一个启动的进程(PID 1)是 systemd。该进程并行化启动多个服务,按需激活进程,自动服务依赖管理。
systemctl list-units 列出所有类型的 unit,-t service,只看 service 相关的。
- 查看服务状态
1 | systemctl status vsftpd |
- 启动和停止服务
1 | systemctl start|stop|restart|reload vsftpd |
- 设置服务是否开机启动或禁用
1 | systemctl enable|disable vsftpd |
- 查看服务启动状态
1 | systemctl is-active vsftpd |
设置系统图形界面启动或字符界面启动
文件 /etc/inittab
显示了设置启动界面的方式
1 | inittab is no longer used. |
使用 systemctl get-default
, 查看当前启动界面。
1 | [root@example Package]# systemctl get-default |
使用 systemctl set-default multi-user.target
设置以字符界面启动,使用 systemctl set-default multi-user.target
设置以图形界面启动。
系统启动流程
-
上电,BIOS 运行,开机自检(POST),初始化硬件
-
固件按照顺序选择可启动的设备,搜索所有设备的主启动记录(MBR)
启动设备有:u盘,本地硬盘,ISO启动,网络启动
-
固件从磁盘读取 boot loader,并将系统控制权交给 boot loader。红帽 8 的 boot loader 为 GRUB2
-
GRUB2 加载
/boot/grub2/grub.cfg
配置文件,选择要启动的内核
红帽 8 的内核在/usr/lib/modules/4.18.0-80-el8x86_64
,里面有许许多多的驱动。用户在终端里执行的一些命令,很多都是调用的这里驱动的一些功能。
这里有个问题,驱动在根目录下面,但是根还没建立起来,要驱动根,而驱动根的驱动就是在根下面。。怎么做呢?
在/boot
目录下,提供了内核和驱动文件,由grub.cfg
文件中的set root = 'hd0 msdos1'
这句话告诉系统/boot
目录所在的分区,如果/boot
目录没有被单独分出来,而是和根分在了一起,那么:
内核文件所在的位置/boot/vmlinuz-4.18.0-80-el8x86_64
驱动文件所在的位置/boot/initramfs-4.18.0-80-el8x86_64.img
如果/boot
目录单独被分出来了,那么
内核文件所在位置可以写成/vmlinuz-4.18.0-80-el8x86_64
驱动文件所在位置/initramfs-4.18.0-80-el8x86_64.img
注意这里的/
不是根文件系统,因为此时根文件系统还未建立,这里指的是 boot 目录所在的分区。 -
boot loader 加载内核和 initramfs 并放入内存中。initramfs 包含启动时硬件必要的内核模块和初始化脚本
以只读的方式加载真正的根 ro root=/dev/mapper/rhel-root
修复 grub.cfg
如果 /boot/grub2/grub.cfg
文件丢失导致系统无法正常启动,修复步骤如下
使用 df -h
查看磁盘的分区情况
-
指定 /boot 目录所在的分区
1
set root='hd0,msdos1'
-
加载内核文件,并以只读的方式加载根分区
1
linux16 /vmlinuz-4.18.0-80-el8x86_64 ro root=/dev/mapper/rhel-root
-
指定 initramfs 文件
1
initrd /initramfs-4.18.0-80-el8x86_64.img
-
启动
1
boot
-
进入系统后重新生成
/boot/grub2/grub.cfg
文件,重启测试1
grub2-mkconfig -o /boot/grub2/grub.cfg
注意,/boot/grub2/grub.cfg
这个文件是根据 /etc/grub.d
和 /etc/default/grub
这两个文件生成的,如果要修改的话修改这两个文件然后重新生成 grub.cfg
。
更改系统启动时内核选择页面的倒计时时间,在 /etc/default/grub
文件的第一行有个 GRUB_TIMEOUT=5
,修改这个数字并重新生成 grub.cfg
即可。
查看内核启动项信息
查看默认启动内核
1 | grubby --default-kernel |
查看内核启动信息
1 | [root@example boot]# grubby --info=ALL |
修改内核默认启动项
内核升级之后,会出现一个新的内核,这个时候可能要修改启动内核(比如驱动没更新新的内核启不来,只能从旧的内核启)
查看当前内核版本
1 | [root@example boot]# uname -r |
两种方式修改内核:
- 根据菜单栏的索引号设置
1 | grubby --set-default 1 |
- 绑定特定版本内核
1 | grubby --set-default /boot/vmlinuz-4.18.0-80.el8.x86_64 |
修改内核启动参数
-
直接修改
/etc/default/grub
文件中的参数定义 -
命令修改
grubby --args=console=ttyS0,115200 --remove-args="rhgb quiet" --update-kernel /boot/vmlinuz-4.18.0-80.el8.x86_64
tips:如何把网卡从 ens0
修改成 eth0
这种方式
修改 /etc/default/grub
加入 net.ifnames=0 biosdevname=0
并更新该文件
修改 root 密码
原理:从 initramfs
运行的脚本在某点暂停,并提供 shell,然后在该 shell 下继续执行,这主要是为了调试,但也可以使用该方法来重置丢失的 root 密码。
中断启动
重启系统,进入这个页面,按 e
在 linux
所在行的末尾添加 rd.break
(中断启动)
ctrl + x
继续启动
重置 root 密码
- 以读写方式挂载
/sysroot
目录
1 | mount -o remount, rw /sysroot |
- 切换至真正操作系统的根
/sysroot
1 | chroot /sysroot |
- 重置密码
1 | echo 123456 | passwd --stdin root |
- 打标签
1 | touch /.autorelabel |
这个文件跟 selinux
相关,是根下面的一个隐藏文件,而且一定不能创建错
exit
退出两次
修复文件系统
/etc/fstab
中的错误和损坏的文件系统可能会阻止系统的启动,系统会进入需要提供 root 密码的紧急修复模式。
系统在启动的时候会读取 /etc/fstab
文件
- 以读写的方式重新挂载根
- 挂载本地其他文件系统
/etc/fstab
文件内容如下
1 | UUID=8768f96f-ad79-4bdf-ac1d-a558444d936e / xfs defaults 0 0 |
常见的文件系统问题:
- 文件系统损坏
/etc/fstab
中引用的设备不存在/etc/fstab
中的挂载点不存在/etc/fstab
中的文件系统类型书写错误/etc/fstab
中的挂载选项错误等
修复步骤
-
进入紧急模式,输入 root 密码
-
尝试挂载所有的文件系统,定位
/etc/fstab
中的问题 -
确保当前根文件系统可读写,若是
ro
,则要改成rw
-
修改成正确的配置
-
重启系统
系统启动流程总结
boot loader 损坏修复
模拟破坏引导程序
1 | dd if=/dev/zero of=/dev/sda bs=446 count=1 |
从光盘启动进入救援模式
切换至真正的跟文件系统 chroot /mnt/sysimage/
修复引导程序 grub2-install /dev/sda
重启测试,选择从本地磁盘启动