LVM(Logical Volume Manager)逻辑卷管理
本文实验部分,完全由本人亲自动手实践得来
文章中有部分的内容是我个人通过实验测试出来的,虽以目前本人的能力还没发现不通之处,但错误难免,所以若各位朋友发现什么错误,或有疑惑、更好的建议等,盼请各位能在评论区不吝留下宝贵笔迹。最后,希望各位能读有所获。
实验环境
[Allen@Centos7 ~]$ uname -r
3.10.0-693.el7.x86_64
[Allen@Centos7 ~]$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
1. LVM基本概念
- LVM:Logical Volume Manager,Version 2
- DM(device mapper):将一个或多个底层块设备组成一个逻辑设备的模块;
- PV(physical volume):物理卷,它在逻辑卷管理系统最底层,可为整个物理硬盘或实际物理硬盘上的分区。
- VG(volume group):卷组,它建立在物理卷上,一卷组中至少要包括一物理卷,卷组建立后可动态的添加卷到卷组中,一个逻辑卷管理系统工程中可有多个卷组。
- LV(logical volume):逻辑卷,它建立在卷组基础上,卷组中未分配空间可用于建立新的逻辑卷,逻辑卷建立后可以动态扩展和缩小空间。
- PE(physical extent):物理区域,它是物理卷中可用于分配的最小存储单元,物理区域大小在建立卷组时指定,一旦确定不能更改,同一卷组所有物理卷的物理区域大小需一致,新的pv加入到vg后,pe的大小自动更改为vg中定义的pe大小。
- LE(logical extent):逻辑区域,它是逻辑卷中可用于分配的最小存储单元,逻辑区域的大小取决于逻辑卷所在卷组中的物理区域的大小。
- 卷组描述区域:卷组描述区域,它存在于每个物理卷中,用于描述物理卷本身、物理卷所属卷组、卷组中逻辑卷、逻辑卷中物理区域的分配等所有信息,它是在使用pvcreate建立物理卷时建立的。
**Note:当多个物理卷组合成一个卷组后时,LVM会在所有的物理卷上做类似格式化的工作,将每个物理卷切成一块一块的空间,这一块一块的空间就称为PE(Physical Extent ),它的默认大小是4MB。
LVM1中每个VG中只能有65534个PE,所以指定PE的大小能改变每个VG的最大容量。但在LVM2中已经没有该限制了,而现在说的LVM一般都指LVM2,这也是默认的版本。
Physical Extent size must be a multiple of 128.00 KiB when not a power of 2. ##物理范围的大小必须是128.00 KiB的倍数,而不是2的幂。
**
VG将每一个PV(块设备)提供的存储空间,划分成统一大小的存储块PE(Physical Extent),PE的大小是在加入到VG之后进行的划分的,每一个VG划分的PE都可能不一样。
在VG的基础上创建LV(逻辑卷),这个LV可以随意格式化。
创建LV的过程,就是分配一些PE给LV。需要增加空间时就再分配一些PE。需要减少一些空间,就拿掉一些PE。而且增加和减少PE的过程不会损坏逻辑分区中现有的数据(理论上)。
Linux自动创建分区的时候,会这样:
创建一个boot分区,剩余其他空间创建成一个PV。然后把这个PV创建成一个VG,VG创建多个LV,一个LV做根分区、一个LV做SWAP分区、一个LV做USR。等等
缺点:
这种方式十分的灵活,非常的方便。但是唯一的缺点就是较为不安全,如果误删除数据了,不好恢复数据。
LV的缩减比较危险。如果某个PV存放了数据。就不能直接挪走了,需要现将PE挪走。
2. pv相关命令
pvcreate ##创建物理卷
一次可以创建n个物理卷
-u ##手动指定UUID
-v ##显示过程
-f ##强制创建(如果里面有数据,则强制覆盖,不管提示)
pvdisplay ##显示详细pv信息
pvmove ##将物理卷上的数据(PE)移动到其他物理卷上去。
pvremove ##移除物理卷
pvck ##检测
pvs ##显示简要pv信息
3. vg相关命令
OPTIONS
vgdisplay ##显示详细vg信息
vgs ##显示简要vg信息
vgcreate ##创建卷组
vgcreate [OPTION] vgname pvname
-s ##指定PE大小,单位可以使bBsSkKmMgG....(不指定PE的话,默认为4.00 MiB),创建了vg之后,他的PE,大小就固定了,只能删除再重新创建时更改
vgmove ##移动 ##参考实例2
vgremove ##移除 ##参考实例2
vgextend ##扩展 ##参考实例1
vgeduce ##缩减
vgsplit ##切割
vgchange ##修改vg属性
-a ##设置vg的状态active还是inactive ##参考实例3
EXAMPLE
实例1
##为这个vg添加pv
[Allen@Centos7 ~]$ sudo vgextend myvg /dev/sda15
Volume group "myvg" successfully extended
实例2
##为这个vg移除pv,移除之前需要先进行move(将有数据的PE移动到其他PV中)
[Allen@Centos7 ~]$ sudo pvmove /dev/sda15
No data to move for myvg
[Allen@Centos7 ~]$ sudo vgreduce myvg /dev/sda15
Removed "/dev/sda15" from volume group "myvg"
实例3
将firstvg设置为活动状态(active yes)。
shell> vgchange -a y firstvg
将firstvg设置为非激活状态(active no)。
shell> vgchange -a n firstvg
4. lv相关命令
OPTIONS
lvs ##显示简要lv信息
lvdisplay ##显示详细lv信息
lvcreate ##创建逻辑卷
-L, --size ##指定逻辑卷大小[mG] ##参考实例1
-n ##lv的名字 ##参考实例1
-l | --extents [+]Number[PERCENT] ##分配的逻辑盘区的数量,也可以指定占据某个vg的百分比,
-VolumeGroup ##指定在哪个卷组中创建
-s,--snapshot ##快照卷
-p,--permission [r|rw] ##设置访问权限
lvreduce
lvreduce -L [-]#[mMgGtT] /dev/VG_NAME/LV_NAME ##不加减号就是缩小到多少。
lvremove ##移除逻辑卷
lvresize ##改变大小
lvconf ##修改lv的配置文件
lvextend ##扩展逻辑卷
-L [+]#[mMgGtT] /dev/VG_NAME/LV_NAME ##参考实例2
指定加号,表示增加多少。
不指定加号,表示希望这个LV能有到多大空间,如果不足就自动加上到满足
-l [+][number] 增加指定数量的PE或让PE达到指定数量
lvconvert ##Change logical volume layout ##参考实例3
--merge 合并快照
EXAMPLE
实例1
在myvg这个卷组山创建LV,指定空间为1.99G,名称为mylv。
[root@Centos7 ~]# lvcreate -L 1.99G -n mylv myvg
Rounding up size to full physical extent 1.99 GiB
Logical volume "mylv" created.
实例2
[root@Centos7 lvm]# lvextend -L 2.5G /dev/myvg/mylv ##将mylv扩张到2.5G
Size of logical volume myvg/mylv changed from 1.99 GiB (510 extents) to 2.50 GiB (640 extents).
Logical volume myvg/mylv successfully resized.
[root@Centos7 ~]# lvextend -l +10 /dev/mapper/testvg-testlv ##通过增加指定数量的PE来实现
Size of logical volume testvg/testlv changed from 2.00 GiB (128 extents) to <2.16 GiB (138 extents).
Logical volume testvg/testlv successfully resized.
实例3
lvconvert --merge /dev/mapper/myvg-mylv-snap
5. resize2fs命令:调整ext文件系统大小
NAME
resize2fs - ext2/ext3/ext4 file system resizer
SYNOPSIS
resize2fs [ -fFpPM ] [ -d debug-flags ] [ -S RAID-stride ] device [ size ]
EXAMPLE
实例1
[root@Centos7 lvm]# lvextend -L 2.5G /dev/myvg/mylv
Size of logical volume myvg/mylv changed from 1.99 GiB (510 extents) to 2.50 GiB (640 extents).
Logical volume myvg/mylv successfully resized.
[root@Centos7 lvm]# df -lh | grep /dev/mapper/myvg-mylv
/dev/mapper/myvg-mylv 2.0G 3.1M 1.9G 1% /mnt/lvm
为什么空间还是2G,这是因为原来的LV是2G大小,文件系统也就是2G大小,现在LV扩大了,但是文件系统还是没有扩大,这时候需要将新增部分指定文件系统
xfs文件系统,则使用xfs_growfs
不指定大小就是将文件系统填充所有PV
[root@Centos7 lvm]# resize2fs /dev/mapper/myvg-mylv
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/mapper/myvg-mylv is mounted on /mnt/lvm; on-line resizing required
old_desc_blocks = 16, new_desc_blocks = 20
The filesystem on /dev/mapper/myvg-mylv is now 2621440 blocks long.
6. LVM实验
6.1 创建lv逻辑卷
1、前提:使用fdisk创建分区,将创建分区,并将分区类型配置成8e
2、将sda14创建为pv
物理卷(Physical Volumes)简称PV,是在磁盘的物理分区或与磁盘分区具有同样功能的设备(如RAID)上创建而来。它只是在物理分区中划出了一个特殊的区域,用于记载与LVM相关的管理参数。
[Allen@Centos7 ~]$ sudo pvcreate /dev/sda14
Physical volume "/dev/sda14" successfully created.
3、创建名字叫myvg的卷组,将sda14(需要提前创建成pv)加入到myvg
卷组(Volume Group)简称VG,它是一个或者多个物理卷的组合。卷组将多个物理卷组合在一起,形成一个可管理的单元,它类似于非LVM系统中的物理硬盘。
[Allen@Centos7 ~]$ sudo vgcreate myvg /dev/sda14
Volume group "myvg" successfully created
为这个vg添加pv
[root@Centos7 ~]# pvcreate /dev/sda15
Physical volume "/dev/sda15" successfully created.
[Allen@Centos7 ~]$ sudo vgextend myvg /dev/sda15
Volume group "myvg" successfully extended
4、在myvg这个卷组上创建LV,指定空间为1.99G,名称为mylv。
逻辑卷(Logical Volumes)简称LV,是在卷组中划分的一个逻辑区域,类似于非LVM系统中的硬盘分区。
[root@Centos7 ~]# lvcreate -L 1.99G -n mylv myvg
Rounding up size to full physical extent 1.99 GiB
Logical volume "mylv" created.
5、将这个分区格式化为ext4
[root@Centos7 ~]# mkfs.ext4 -b 1024 -l MYLV /dev/myvg/mylv
6、执行挂载
[root@Centos7 ~]# mkdir /mnt/lvm
[root@Centos7 ~]# mount /dev/myvg/mylv /mnt/lvm/
##可以看出来,不管在挂在的时候使用的是什么路径,显示的时候,都是/dev/mapper/xxxx
[root@Centos7 ~]# blkid | grep MYLV
/dev/mapper/myvg-mylv: LABEL="MYLV" UUID="7fc94efc-098c-40ff-aef8-44efc5e189a4" TYPE="ext4"
[root@Centos7 ~]# mount | grep mnt/lvm
/dev/mapper/myvg-mylv on /mnt/lvm type ext4 (rw,relatime,seclabel,stripe=4,data=ordered)
Note:推荐第一种方式
创建好LV之后,有两种路径名称都可以访问到这个LV。分别是以下两种格式
/dev/mapper/VG_NAME-LV_NAME
[root@Centos7 ~]# ls -l /dev/mapper/myvg-mylv
lrwxrwxrwx. 1 root root 7 Aug 27 17:01 /dev/mapper/myvg-mylv -> ../dm-2
/dev/VG_NAME/LV_NAME
[root@Centos7 ~]# ls -l /dev/myvg/mylv
lrwxrwxrwx. 1 root root 7 Aug 27 17:01 /dev/myvg/mylv -> ../dm-2
6.2 扩展逻辑卷
当卷组中没有足够的空间用于扩展逻辑卷的大小时,就需要增加卷组的容量,而增加卷组容量的惟一办法就是向卷组中添加新的物理卷。
首先是增加一块新硬盘,并对其完成分区、创建物理卷等工作。接下来是利用vgextend命令将新的物理卷(/dev/sda16)加入到卷组中。
完成卷组的扩容后,使用lvextend命令增加空间给lv,实现分区的动态调整。
[root@Centos7 lvm]# lvextend -L 2.5G /dev/myvg/mylv
Size of logical volume myvg/mylv changed from 1.99 GiB (510 extents) to 2.50 GiB (640 extents).
Logical volume myvg/mylv successfully resized.
此步骤不算在扩展逻辑卷中,只作为实例
[root@Centos7 ~]# lvextend -l +10 /dev/mapper/testvg-testlv ##也可以通过增加指定数量的PE来实现(需要加多找个PE,需要自己算)
Size of logical volume testvg/testlv changed from 2.00 GiB (128 extents) to <2.16 GiB (138 extents).
Logical volume testvg/testlv successfully resized.
[root@Centos7 lvm]# df -lh | grep /dev/mapper/myvg-mylv
/dev/mapper/myvg-mylv 2.0G 3.1M 1.9G 1% /mnt/lvm
为什么空间还是2G,这是因为原来的LV是2G大小,文件系统也就是2G大小,现在LV扩大了,但是文件系统还是没有扩大,这时候需要将新增部分指定文件系统
##不指定大小就是将文件系统填充所有PV
[root@Centos7 lvm]# resize2fs /dev/mapper/myvg-mylv
resize2fs 1.42.9 (28-Dec-2013)
Filesystem at /dev/mapper/myvg-mylv is mounted on /mnt/lvm; on-line resizing required
old_desc_blocks = 16, new_desc_blocks = 20
The filesystem on /dev/mapper/myvg-mylv is now 2621440 blocks long.
6.3 缩减逻辑卷(危险,不建议)
xfs文件系统,则使用xfs_growfs
- umount /dev/VG_NAME/LV_NAME
- e2fsck -f /dev/VG_NAME/LV_NAME ##文件系统的强制检测和修复
- resize2fs /dev/VG_NAME/LV_NAME n# ##缩减到多大,将逻辑边界缩小(要确保缩减后的空间,可以容纳现有数据)
- lvreduce -L [-]#[mMgGtT] /dev/VG_NAME/LV_NAME 不加减号就是缩小到多少。
1、卸载挂载点
[root@Centos7 ~]# umount /mnt/lvm/
2、强制执行检测与修复(检查是否修改后的大小会影响数据)
[root@Centos7 ~]# e2fsck -f /dev/myvg/mylv
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
MYLV: 13/163840 files (0.0% non-contiguous), 77665/2621440 blocks
3、缩小文件系统,原来是2.5G,现在指定成2G(我指定过1.8但是报错了,没有成功)
[root@Centos7 ~]# resize2fs /dev/myvg/mylv 2G
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/myvg/mylv to 2097152 (1k) blocks.
The filesystem on /dev/myvg/mylv is now 2097152 blocks long.
4、缩小lv,可以直接使用"-L"指定收缩容量,也可以使用"-l"指定收缩的PE数量。
发现有警告:可能会损毁你的数据。如果在该lv下存储的实际数据大于收缩后的容量,那么肯定会损毁一部分数据,但是如果存储的数据小于收缩后的容量,那么就不会损毁任何数据,这是lvm无损修改分区大小的优点。此处由于在lv下完全没有存储数据,所以无需担心会损毁,直接y确定reduce。
[root@Centos7 ~]# lvreduce -L 2G /dev/myvg/mylv
WARNING: Reducing active logical volume to 2.00 GiB.
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce myvg/mylv? [y/n]: y
Size of logical volume myvg/mylv changed from 2.50 GiB (640 extents) to 2.00 GiB (512 extents).
Logical volume myvg/mylv successfully resized.
##如果仅仅为了缩小LV的空间,那么已经结束,可以直接执行第8步操作。如果想要把一块硬盘将vg中移除,继续第五步。
5、pvmove移动PE
首先确定好想要移除哪块硬盘。
然后确定经过缩减之后,缩减掉的空间,大于想移除的那块硬盘的空间。
因为不确定缩减掉空间,是来源于那块硬盘的,所以查看每块硬盘的pe使用情况(通过pvdisplay与pvscan)
如果指定硬盘的PE被占用,则不可以从vg中移除,需要执行pvmove命令,将该硬盘上的PE移动到其他硬盘上才可以。
例如:想要移除/dev/sda15,但是/dev/sda15上还有数据,则将/dev/sda15的数据移动到/dev/sda17(其实不用将全部PE移动,可以通过pvdisplay -m /dev/sda#查看哪些PE在使用,只把正在使用的PE移动过即可)
[root@Centos7 ~]# pvmove /dev/sda15:0-254 /dev/sda17
/dev/sda15: Moved: 0.00%
/dev/sda15: Moved: 56.86%
/dev/sda15: Moved: 100.00%
6、从vg中移除pv
使用pvdisplay -m /dev/sda# 查看是否还有PE被占用,如果没有则执行移除
例如:
[root@Centos7 ~]# vgreduce myvg /dev/sda15
Removed "/dev/sda15" from volume group "myvg"
7、移除该pv
[root@Centos7 ~]# pvremove /dev/sda15
Labels on physical volume "/dev/sda15" successfully wiped.
8、重新执行mount
[root@Centos7 ~]# mount /dev/myvg/mylv /mnt/lvm/
7. Snapshot
7.1 基本概念
- 序列化:把本来有形状的,有组织格式的数据,转换成能够流式化传输的机制。
- 快照首先要快,否则可能会造成各部分数据不匹配(先扫描的旧,后扫描的新。导致数据组合不起来)
下面这部分LVM快照原理与图片部分,摘自Linux公社的文章:基于LVM的快照实现原理分析
LVM快照原理
LVM对LV提供的快照功能,只对LVM有效。
当一个snapshot创建的时候,仅拷贝原始卷里数据的元数据(meta-data)。创建的时候,并不会有数据的物理拷贝,因此snapshot的创建几乎是实时的,当原始卷上有写操作执行时,snapshot跟踪原始卷块的改变,这个时候原始卷上将要改变的数据在改变之前被拷贝到snapshot预留的空间里,因此这个原理的实现叫做写时复制(copy-on-write)。
在写操作写入块之前,将原始数据移动到 snapshot空间里,这样就保证了所有的数据在snapshot创建时保持一致。而对于snapshot的读操作,如果是读取数据块是没有修改过的,那么会将读操作直接重定向到原始卷上,如果是要读取已经修改过的块,那么就读取拷贝到snapshot中的块。
创建snapshot的大小并不需要和原始卷一样大,其大小仅仅只需要考虑两个方面:从shapshot创建到释放这段时间内,估计块的改变量有多大;数据更新的频率。一旦 snapshot的空间记录满了原始卷块变换的信息,那么这个snapshot立刻被释放,从而无法使用,从而导致这个snapshot无效。
创建快照
在快照创建的时候,仅拷贝原始卷里数据的元数据(meta-data),并生成位图记录原始卷的块数据变化。
读写原始卷
在创建完快照后,对原始卷的读写请求处理流程如下。
-
写原始卷 在原始卷的写入数据
- 检查Chunk位图中要写入数据所在的Chunk所对应的bitmap是否被置位;
- 如果已被置位,直接写入该Chunk;如果未被置位,将拷贝该Chunk的数据到快照备份卷;
- 将Chunk位图中对应的bitmap置位。
- 将数据写入原始卷。
-
读原始卷
- 直接从原始卷对应的Chunk中读取数据。
- 直接从原始卷对应的Chunk中读取数据。
-
读写快照
- 读快照
- 在处理快照的读请求时,检查Chunk位图是否置位,如果置位从快照读取数据;如果未置位,则从原始卷读取数据。如下图所示:
- 在处理快照的读请求时,检查Chunk位图是否置位,如果置位从快照读取数据;如果未置位,则从原始卷读取数据。如下图所示:
- 读快照
-
写快照
在处理快照的写请求时,- 检查Chunk位图是否置位,如果置位直接写快照;
- 如果未置位,则从原始卷读取该Chunk的数据,拷贝到快照卷;
- 将Chunk位图中对应的位图置位;
- 将数据写入快照卷;
7.2 创建快照
创建快照的命令格式
lvcreate –L #[mMgGtT] –p r –s –n snapshot_lv_name original_lv_name
Note:快照卷通常是只读的,所以分配-r即可。
[Allen@Centos7 ~]$ sudo lvcreate -s -L 512M -n mylv-snap -p r /dev/myvg/mylv
Using default stripesize 64.00 KiB.
Logical volume "mylv-snap" created.
[Allen@Centos7 ~]$ sudo mkdir /mnt/snap ; sudo mount /dev/myvg/mylv-snap /mnt/snap
mount: /dev/mapper/myvg-mylv--snap is write-protected, mounting read-only
复制一个新文件到原卷,快照卷不会发生变化,因为快照卷只复制发生变化的文件。
7.3 恢复快照
7.3.1 方法一
[root@Centos7 ~]# lvdisplay /dev/mapper/testvg-testlv ##查看逻辑卷状态
--- Logical volume ---
LV Path /dev/testvg/testlv
LV Name testlv
VG Name testvg
LV UUID iPAbi5-foGP-0zqc-zvpb-4eLo-3aeu-fYhV3z
LV Write Access read/write
LV Creation host, time Centos7.4, 2018-08-28 10:35:03 +0800
LV snapshot status source of
testlv-snap [active]
LV Status available
# open 1
LV Size 2.00 GiB
Current LE 128
Segments 3
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 253:2
[root@Centos7 ~]# umount /dev/myvg/mylv-snap ##卸载快照的挂载点
[root@Centos7 ~]# umount /dev/myvg/mylv ##卸载原卷的挂载点
[root@Centos7 ~]# lvconvert --merge /dev/myvg/mylv-snap ##执行快照恢复
Merging of volume myvg/mylv-snap started.
testlv: Merged: 96.38%
testlv: Merged: 100.00%
查看文件,发现所有文件的状态和内容都回复到做快照的那个时间点了。而且快照文件没有了
[root@Centos7 ~]# lvdisplay /dev/mapper/testvg-testlv ##查看逻辑卷状态
--- Logical volume ---
LV Path /dev/testvg/testlv
LV Name testlv
VG Name testvg
LV UUID iPAbi5-foGP-0zqc-zvpb-4eLo-3aeu-fYhV3z
LV Write Access read/write
LV Creation host, time Centos7.4, 2018-08-28 10:35:03 +0800
LV Status available
# open 1
LV Size 2.00 GiB
Current LE 128
Segments 3
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 253:2
7.3.2 方法二
这种方式我只做过一次,环境及方法如下
1、做一个镜像
dd if=/dev/vg_image/lv_image_snap of=/data/recover.img
##确保/data拥有足够的空间,这个相当于做了原卷的镜像。因为snapshot只是原卷数据的另一个通路。访问没有发生变化的数据会指向原卷,访问原卷上发现变化的数据会指向snapshot本身(在发生变化的时候,会先拷贝一份数据到snapshot卷),所以这个dd是对快照时间点的所有原卷做了镜像。
2、删除snapshot
umount XXX
lvremove /dev/vg_image/lv_image_snap
3、卸载原卷挂载点
umount XXX
4、执行恢复
dd if=/data/recover.img of=/dev/vg_new/lv_new
5、重新挂载原卷
已恢复之前挂载的状态了(只是简单地查看一些文件内容和时间戳)
7.4 移除快照
lvremove /dev/myvg/mylv-snap
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!