LiangGaRy-学习笔记-Day18

1、知识回顾

1.1、磁盘管理

磁盘使用之前需要先格式化,格式化之前需要先分区,也就先分区再格式化才能使用
linux磁盘管理大致分为五个步骤:首先添加相应的磁盘(/dev/sda、sdb、sdc、sde…),然后是对相应磁盘分区,分区完之后是格式化,最后是挂载使用,不用的时候卸载

  • 分区:
    • 使用的就是fdisk命令–>MBR格式
    • parted命令–>GPT格式
  • 创建文件系统:
    • mkfs.ext[2-4]:ext文件系统
    • mkfs.xfs:就是CentOS7以上的系统类型
  • 挂载使用:
    • mount 设备文件 + 目录
#分区:
[root@Node1 ~]# fdisk /dev/sdb
............
Command (m for help): n
Partition number (3-128, default 3): 
First sector (34-41943006, default 35653632): 
Last sector, +sectors or +size{
    
    K,M,G,T,P} (35653632-41943006, default 41943006): +1G
Created partition 3
Command (m for help): w

#parted命令-->进行分区
[root@Node1 ~]# parted  /dev/sdb
[root@Node1 ~]# parted  /dev/sdb
.................
(parted) mklabel msdos

#创建文件系统
[root@Node1 ~]# mkfs.xfs -f /dev/sdb1

#创建目录,然后挂在使用
[root@Node1 ~]# mkdir /sdb1/
[root@Node1 ~]# mount /dev/sdb1  /dev/sdb1

1.2、fdisk分区命令

作用:用于磁盘分区,以及查询磁盘分区状态

语法:fdisk + 选项 + 磁盘

选项:

  • -l:查看磁盘分区表
  • -s:指定分区块的大小
#查看磁盘状态;-l
[root@Node1 ~]# fdisk  -l /dev/sdc 

Disk /dev/sdc: 21.5 GB, 21474836480 bytes, 41943040 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

#查看磁盘分区的几种方法
[root@Node1 ~]# ls /dev/sd*
/dev/sda  /dev/sda1  /dev/sda2  /dev/sdb  /dev/sdc

[root@Node1 ~]# lsblk 
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   20G  0 disk 
├─sda1            8:1    0  500M  0 part /boot
└─sda2            8:2    0 19.5G  0 part 
  ├─centos-root 253:0    0 18.5G  0 lvm  /
  └─centos-swap 253:1    0    1G  0 lvm  [SWAP]
sdb               8:16   0   20G  0 disk 
sdc               8:32   0   20G  0 disk 
sr0              11:0    1  4.3G  0 rom  

1.3、开机自动挂载

涉及的文件就是/etc/fstab文件

  • 这个文件就是涉及自动挂在分区的文件
  • 其内容与解析如下:
#编辑/etc/fstab文件
[root@Node1 ~]# vim /etc/fstab 
/dev/mapper/centos-root /                       xfs     defaults        0 0
/dev/sr0	/mnt/cdrom	iso9660	defaults	0	0

#详细信息解释如下:
	/dev/sr0:表示需要挂载的分区设备
	/mnt/cdrom:表示挂载点;具体挂载到哪儿
	ISO9660:代表的就是文件系统类型
	defaults:表示挂载选项
	0:表示是否备份
	0:表示是否检测

#defaults挂载选项说明
Async/sync:设置是否为同步方式运行,默认为async
auto/noauto:当下载mount -a 的命令时,此文件系统是否被主动挂载。默认为auto
rw/ro:是否以以只读或者读写模式挂载
exec/noexec:限制此文件系统内是否能够进行"执行"的操作
user/nousee:是否允许用户使用mount命令挂载
suid/nosuid:是否允许SUID的存在
Usrquota:启动文件系统支持磁盘配额模式
Grpquota:启动文件系统对群组磁盘配额模式的支持
Defaults:同事具有rw,suid,dev,exec,auto,nouser,async等默认参数的设置

2、GPT分区说明

2.1、gdisk命令

作用:主要是用于划分容量大于2T的硬盘;

  • 硬盘容量大于2T的,fdisk命令就没法分区;

说明:

  • 分区表有两种
    • GPT:gpt分区,全局唯一表示分区表
      • GPT提供分区表信息的冗余,一个在磁盘头部一个在磁盘尾部
      • 具有CRC校验:一个硬盘可以支持128个主分区
    • MBR分区:
      • 最多有四个主分区
      • 一个扩展分区
        • 扩展分区又可以划出逻辑分区

语法:gdisk + 选项 + 设备

选项:-l :指定设备的分区表信息

操作菜单说明:

  • b:将GPT数据备份到一个文件
  • c:更改分区名称
  • d:删除一个分区
  • i:显示分区详细信息
  • l:列出已知分区类型。
  • n:增加一个新的分区
  • o:创建一个新的空白的GPT分区表
  • p:显示当前磁盘的分区表
  • q:退出gdisk程序,不保存任何修改
  • r:恢复和转换选项(仅限专家)
  • s:排序分区
  • t:改变分区的类型
  • v:验证磁盘分区表
  • w:将分区表保存并退出
  • x:额外功能(仅限专家)
  • ?:显示帮助信息
[root@Node1 ~]# gdisk /dev/sdb
............#基本个fdisk命令一致..............
Command (? for help): n       
Partition number (2-128, default 2): 
First sector (34-41943006, default = 4196352) or {
    
    +-}size{
    
    KMGTP}:  
Last sector (4196352-41943006, default = 41943006) or {
    
    +-}size{
    
    KMGTP}: +2G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 
Changed type of partition to 'Linux filesystem'

Command (? for help): w

2.2、gdisk分区实战

对sdb进行分区:

扫描二维码关注公众号,回复: 15252053 查看本文章
  • 修改sdb为gpt分区
  • 然后使用gdisk命令进行分区
#修改/dev/sdb的分区格式-->使用parted命令
[root@Node1 ~]# parted 
GNU Parted 3.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) select /dev/sdb
Using /dev/sdb
(parted) mklabel gpt                                                      
Warning: The existing disk label on /dev/sdb will be destroyed and all data on
this disk will be lost. Do you want to continue?
Yes/No? y    

#然后查看一下分区
[root@Node1 ~]# lsblk                                                     
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0   20G  0 disk 
├─sda1            8:1    0  500M  0 part /boot
└─sda2            8:2    0 19.5G  0 part 
  ├─centos-root 253:0    0 18.5G  0 lvm  /
  └─centos-swap 253:1    0    1G  0 lvm  [SWAP]
sdb               8:16   0   20G  0 disk 
sdc               8:32   0   20G  0 disk 
└─sdc1            8:33   0    1G  0 part 
sr0              11:0    1  4.3G  0 rom  /mnt/cdrom

#对/dev/sdb进行分区
[root@Node1 ~]# gdisk 
..............
Type device filename, or press <Enter> to exit: /dev/sdb		#选择sdb进行分区
	#查看一下分区情况
Command (? for help): p
..........
Number  Start (sector)    End (sector)  Size       Code  Name
	#新建一个新分区
Command (? for help): n						#n代表新建一个分区
Partition number (1-128, default 1): 1		#分区号从1开始
First sector (34-41943006, default = 2048) or {
    
    +-}size{
    
    KMGTP}: 	#选择默认就可以
	#分区的大小为2G
Last sector (2048-41943006, default = 41943006) or {
    
    +-}size{
    
    KMGTP}: +2G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 
Changed type of partition to 'Linux filesystem'

Command (? for help): w	#保存
Do you want to proceed? (Y/N): y			#确定分区
OK; writing new GUID partition table (GPT) to /dev/sdb.
The operation has completed successfully.

#然后查看一下是否创建成功
Command (? for help): quit 
[root@Node1 ~]# lsblk /dev/sdb
NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdb      8:16   0  20G  0 disk 
└─sdb1   8:17   0   2G  0 part 

#格式化分区
[root@Node1 ~]# mkfs.xfs  -f /dev/sdb1

#然后挂在使用
[root@Node1 ~]# mount /dev/sdb1  /sdb1/

3、拓展swap分区

3.1、swap分区说明

swap分区是指在Linux操作系统中为了提高系统运行效率而设置的一块特殊的硬盘空间,也称为虚拟内存。

当系统内存不足时,会将一部分不常用的内存数据存储到swap分区中,以释放内存空间,从而保证系统的稳定运行。

swap分区的大小一般设置为物理内存大小的两倍,但也可以根据实际情况进行调整

查看swap分区命令:

  • free命令可以查看
  • swapon命令也可以查看

swap分区是可以修改大小的:

#查看swap分区
[root@Node1 ~]# free
              total        used        free      shared  buff/cache   available
Mem:        2028116       97244     1734376        9644      196496     1755736
Swap:       1048572           0     1048572

#查看swap分区
[root@Node1 ~]# swapon 
NAME      TYPE       SIZE USED PRIO
/dev/dm-1 partition 1024M   0B   -2

#创建两个分区,用于增加swap分区
[root@Node1 ~]# gdisk /dev/sdb
...............
Command (? for help): n
Partition number (2-128, default 2): 
First sector (34-41943006, default = 4196352) or {
    
    +-}size{
    
    KMGTP}: 
Last sector (4196352-41943006, default = 41943006) or {
    
    +-}size{
    
    KMGTP}: +2G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 
Changed type of partition to 'Linux filesystem'

Command (? for help): n
Partition number (3-128, default 3): 
First sector (34-41943006, default = 8390656) or {
    
    +-}size{
    
    KMGTP}: 
Last sector (8390656-41943006, default = 41943006) or {
    
    +-}size{
    
    KMGTP}: +1G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300): 
Changed type of partition to 'Linux filesystem'

3.2、通过分区增加swap

swap分区:当你内存不够用的时候,会把硬盘一部分空间释放;来供程序使用

  • 第一步需要把刚创建的分区格式化成为swap格式
  • 然后激活swap分区;把它加入到swap分区当中
#把创建好的分区做成swap格式
[root@Node1 ~]# mkswap  /dev/sdb2
mkswap: /dev/sdb2: warning: wiping old xfs signature.
Setting up swapspace version 1, size = 2097148 KiB
no label, UUID=56721914-2d62-4c56-bb2a-15d3be25f24e

#然后开启swap扩容--->swapon
[root@Node1 ~]# swapon  /dev/sdb2

#最后查看一下-->就发现多了2G的swap空间
[root@Node1 ~]# swapon 
NAME      TYPE       SIZE USED PRIO
/dev/dm-1 partition 1024M   0B   -2
/dev/sdb2 partition    2G   0B   -3

3.3、通过文件增加swap

这个实验就是想通过文件增加SWAP空间

  • Linux系统中有个/dev/zero的空洞文件;可以生成无限的字符
    • 用dd命令形成一个文件
  • 然后在创建swap格式
  • 最后添加上去
#生成一个文件
[root@Node1 ~]# dd if=/dev/zero  of=swap_file bs=10M count=100
100+0 records in
100+0 records out
1048576000 bytes (1.0 GB) copied, 19.48 s, 53.8 MB/s

#查看文件的状态
[root@Node1 ~]# stat swap_file 
  File: ‘swap_file’
  Size: 1048576000	Blocks: 2048000    IO Block: 4096   regular file
Device: fd00h/64768d	Inode: 33574988    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-06-29 15:28:30.475083989 +0800
Modify: 2023-06-29 15:28:49.755085846 +0800
Change: 2023-06-29 15:28:49.755085846 +0800
 Birth: -

#修改权限
[root@Node1 ~]# chmod 0600 /root/swap_file 

#然后行程swap格式的分区
[root@Node1 ~]# mkswap -f /root/swap_file 
Setting up swapspace version 1, size = 1023996 KiB
no label, UUID=8934ef2c-ee63-4604-8888-cdf0fa309d63

#最后添加上去
[root@Node1 ~]# swapon  /root/swap_file
	#查看一下情况
[root@Node1 ~]# swapon 
NAME            TYPE       SIZE USED PRIO
/dev/dm-1       partition 1024M   0B   -2
/dev/sdb2       partition    2G   0B   -3
/root/swap_file file      1000M   0B   -4

4、误删除文件恢复

4.1、文件系统说明

文件系统的组成:

  • 文件名、inode、block

修改了配置文件,只要是修改了就需要重启;

  • 原理:
    • 如果一个文件–>有一个inode
    • 修改了文件–>inode号就改变
    • 因此就需要重启来重新获取新的inode
#使用stat命令查看文件信息
[root@Node1 ~]# stat swap_file 
  File: ‘swap_file’
  Size: 1048576000	Blocks: 2048000    IO Block: 4096   regular file
Device: fd00h/64768d	Inode: 33574988    Links: 1
Access: (0600/-rw-------)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-06-29 15:31:48.647103077 +0800
Modify: 2023-06-29 15:31:28.521101139 +0800
Change: 2023-06-29 15:31:28.521101139 +0800
 Birth: -

#查看inode
[root@Node1 ~]# ls -li swap_file 
33574988 -rw------- 1 root root 1048576000 Jun 29 15:31 swap_file

#如果修改文件,那么inode号也会跟着改变
[root@Node1 ~]# ls -i aa.txt 
33574989 aa.txt
[root@Node1 ~]# vim aa.txt 
sdfjsdlfjl1111
[root@Node1 ~]# ls -i aa.txt 
33654984 aa.txt

4.2、文件误删除的处理思维

如果遇到了误删除文件;应该如何操作?

  • 想着辞职?
  • 想着跑路?
  • 还是原地等死?
  • 明显都是错误的;

第一件事情:

  • 防止覆盖
    • 卸载分区
    • 设置只读权限
#创建文件-->查看一下inode
[root@Node1 ~]# touch bb.txt
[root@Node1 ~]# ls -i bb.txt
33574987 bb.txt

#现在删除文件,再创建同名字文件-->在查看inode
[root@Node1 ~]# rm -rf bb.txt 
[root@Node1 ~]# ls -i bb.txt
ls: cannot access bb.txt: No such file or directory
[root@Node1 ~]# touch bb.txt
[root@Node1 ~]# ls -i bb.txt 
33574987 bb.txt

#出现上述的情况解释如下:
-	删除文件等同于释放inode号
-	创建新文件,文件会优先抢占前面被释放的inode

#尽管文件名不同也不会影响这个规则
[root@Node1 ~]# rm -rf bb.txt 
[root@Node1 ~]# touch cc.txt
[root@Node1 ~]# ls -i cc.txt 
33574987 cc.txt

4.3、文件误删除后恢复实战

首先确保:条件一致

  • 系统:CentOS6.X
  • 工具:extundelete(提前准备好这个包)

过程如下:

  • 创建一块硬盘
    • 虚拟机–>右键–>设置–>添加–>硬盘–>然后全部选择下一步即可完成
#进系统查看硬盘
[root@Node1 ~]# ls /dev/sdc
/dev/sdc
  • 分区
    • 这里创建一个5G的分区,用于测试
    • 使用echo命令–>跳过非交互式
#创建分区
	#其实就是把交互式的输入给到echo命令
[root@Node1 ~]# echo -e "n\np\n1\n\n+5G\nw" | fdisk  /dev/sdb 
	#然后判断一下执行是否成功
[root@Node1 ~]# echo $?
0
	#最好查看一下是否有sdb1
[root@Node1 ~]# ls /dev/sdb1
/dev/sdb1
  • 格式化
    • 这里创建mkfs.ext4文件系统
[root@Node1 ~]# mkfs.ext4 /dev/sdb1
...................
This filesystem will be automatically checked every 25 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

#到这里为止创建文件系统已经完成;
  • 挂载分区
    • 创建目录–>用于挂载
#创建目录
[root@Node1 ~]# mkdir -p /sdb1
#挂载
[root@Node1 ~]# mount /dev/sdb1 /sdb1/
  • 创建文件
    • 这里包括空文件,空目录等等
#准备好文件
[root@Node1 ~]# cd /sdb1/
[root@Node1 sdb1]# cp -a /etc/passwd .
[root@Node1 sdb1]# mkdir -p a/b/c
[root@Node1 sdb1]# cp /etc/hosts ./a/b/
[root@Node1 sdb1]# touch a/aa.txt

#最后查看一下目录树
[root@Node1 sdb1]# tree  
.
├── a
│   ├── aa.txt				#这个是空文件
│   └── b
│       ├── c				#这个是空目录
│       └── hosts
├── lost+found
└── passwd
  • 卸载分区
    • 这里要模拟删除数据
    • 然后就卸载分区
#删除文件
[root@Node1 sdb1]# pwd
/sdb1
[root@Node1 sdb1]# rm -rf ./*

#卸载分区
[root@Node1 sdb1]# cd
[root@Node1 ~]# umount /dev/sdb1

#查看一下分区情况
[root@Node1 ~]# df -h 
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda3              18G  1.8G   15G  11% /
tmpfs                 932M     0  932M   0% /dev/shm
/dev/sda1             291M   37M  240M  14% /boot
/dev/sr0              4.1G  4.1G     0 100% /mnt/cdrom
  • 恢复文件
    • 上传extundelete工具
    • 配置变异环境
#准备extundelete工具
[root@Node1 ~]# rz
[root@Node1 ~]# ls extundelete-0.2.4.tar.bz2 
extundelete-0.2.4.tar.bz2

#解压包
[root@Node1 ~]# tar -xf extundelete-0.2.4.tar.bz2 

#创建一个软链接
[root@Node1 ~]# ln -s /root/extundelete-0.2.4 extundelete
#进入到目录
[root@Node1 ~]# cd extundelete
[root@Node1 extundelete]# 

#配置变异环境
[root@Node1 extundelete]# yum -y install gcc gcc-c++ 

#编译安装extundelete-->这里直接报错
[root@Node1 extundelete]# ./configure 
[root@Node1 extundelete]# ./configure 
Configuring extundelete 0.2.4
configure: error: Can't find ext2fs library

#报错明显缺少ext2fs
[root@Node1 extundelete]# yum -y install e2fsprogs-devel

#然后在重新编译
[root@Node1 extundelete]# ./configure && make  && make install
Configuring extundelete 0.2.4
Writing generated files to disk
make -s all-recursive
Making all in src
extundelete.cc:571: warning: unused parameter ‘flags’
Making install in src
  /usr/bin/install -c extundelete '/usr/local/bin'		#这里代表编译完成

#查看命令是否有报错
[root@Node1 extundelete]# echo $?
0

恢复文件

  • 查看一下被删除的文件
  • 可以通过inode号恢复
  • 通过文件名恢复
  • 通过目录名恢复
  • 恢复所有文件
#判断哪些文件被删除
[root@Node1 ~]# extundelete /dev/sdb1
[root@Node1 ~]# extundelete /dev/sdb1 --inode 2
...............
File name                                       | Inode number | Deleted status
.                                                 2
..                                                2
lost+found                                        11             Deleted
passwd                                            12             Deleted
a                                                 128257         Deleted

#到这里可以通过inode号进行恢复
[root@Node1 ~]# mkdir  /test
[root@Node1 ~]# cd /test/
	#这里的12是passwd的inode号
[root@Node1 test]# extundelete  /dev/sdb1 --restore-inode 12
NOTICE: Extended attributes are not restored.
Loading filesystem metadata ... 41 groups loaded.
Loading journal descriptors ... 48 descriptors loaded.
	#这里代表恢复成功
[root@Node1 test]# cd RECOVERED_FILES/
[root@Node1 RECOVERED_FILES]# ls
file.12

#使用md5sum命令判断-->这里是同一个文件
[root@Node1 RECOVERED_FILES]# md5sum  file.12  /etc/passwd
5abbdc210c8e005a4868b631880623c8  file.12
5abbdc210c8e005a4868b631880623c8  /etc/passwd

#通过文件名来恢复
[root@Node1 test]# extundelete  /dev/sdb1 --restore-file passwd
NOTICE: Extended attributes are not restored.
Loading filesystem metadata ... 41 groups loaded.
Loading journal descriptors ... 48 descriptors loaded.
Successfully restored file passwd

#再校验查看
[root@Node1 test]# cd RECOVERED_FILES/
[root@Node1 RECOVERED_FILES]# md5sum passwd /etc/passwd
5abbdc210c8e005a4868b631880623c8  passwd
5abbdc210c8e005a4868b631880623c8  /etc/passwd

#通过目录名来恢复
[root@Node1 test]# extundelete  /dev/sdb1 --restore-directory a
NOTICE: Extended attributes are not restored.
Loading filesystem metadata ... 41 groups loaded.
Loading journal descriptors ... 48 descriptors loaded.
Searching for recoverable inodes in directory a ... 
6 recoverable inodes found.
Looking through the directory structure for deleted files ... 
3 recoverable inodes still lost.
	#再校验查看
[root@Node1 RECOVERED_FILES]# tree a
a
└── b
    └── hosts

1 directory, 1 file

#恢复所有的文件
[root@Node1 test]# extundelete  /dev/sdb1 --restore-all
NOTICE: Extended attributes are not restored.
Loading filesystem metadata ... 41 groups loaded.
Loading journal descriptors ... 48 descriptors loaded.
Searching for recoverable inodes in directory / ... 
6 recoverable inodes found.
Looking through the directory structure for deleted files ... 
0 recoverable inodes still lost.
	#校验查看-->这里可以发现空文件和空目录是没有被恢复的
[root@Node1 test]# cd RECOVERED_FILES/
[root@Node1 RECOVERED_FILES]# tree
.
├── a
│   └── b
│       └── hosts
└── passwd

	#ext4⽂件系统中,extundelete恢复数据,默认情况会认为空⽬录和空⽂件没有恢复的必要

5、文件系统结构

5.1、文件系统的组成

文件系统的组成部分:

  • 文件名、inode 、和block块

Linux文件系统:

  • ext3、ext4、xfs

Windows文件系统:

  • NTFS、FAT32

5.2、inode号说明

文件存储在硬盘上,硬盘的最小存储单位:扇区

  • 每个扇区存储512字节
  • block:块–>一次性读取
  • 4kb=8个扇区
  • 文件数据都是存储在块当中;
  • inode就是索引

inode包含的东西:

  • 文件的字节数
  • 文件拥有者UID
  • 文件所属组GID
  • 文件的读写权限
  • 文件的时间戳
    • ctime:inode上一次变动的时间
    • mtime:文件内容上次变动的时间
    • atime:文件上次访问的时间
#查看目录的信息
[root@Node1 ~]# stat extundelete
  File: `extundelete' -> `/root/extundelete-0.2.4'
  Size: 23        	Blocks: 0          IO Block: 4096   symbolic link
Device: 803h/2051d	Inode: 788534      Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-06-01 14:36:39.062119711 +0800
Modify: 2023-05-30 18:29:04.494375926 +0800
Change: 2023-05-30 18:29:04.494375926 +0800

inode大小说明

  • 数据区:block
  • inode区
  • inode节点的大小:128字节、256字节
  • inode格式化的时间定下来:12.8%
  • inode都有一个号码,用来识别文件

打开一个文件:

  • 系统先查找inode号
  • 通过inode号获取inode的信息.
  • 根据inode信息找到block 读取数据
#查看inode号
[root@Node1 ~]# ls -i 
788504 anaconda-ks.cfg

#查看inode总数和已经使用的数量
[root@Node1 ~]# df -i
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/sda3            1160992   52140 1108852    5% /
tmpfs                 238344       1  238343    1% /dev/shm
/dev/sda1              76912      39   76873    1% /boot

#查找根下0字节的文件并且删除-->释放inode号
[root@Node1 ~]# find / type f -size 0 -exec rm {} \;

猜你喜欢

转载自blog.csdn.net/Liang_GaRy/article/details/131003076