Ubuntu减小swap分区大小的方法

这几天在新买的服务器上装上了Ubuntu Server 14.04,然而安装系统时没注意swap分区大小设置,导致swap分区占用了很大的磁盘空间,因为服务器本身的内存就很大,所以显然不需要分配这么多swap空间,在网上搜索一番找到了减小swap空间的方法,记录于此。

定位swap分区

首先要确定swap分区的位置才能进行之后的调整操作,可以简单的使用free -h命令查看当前内存及swap空间的使用情况:

1
2
3
4
5
6
# free -h

total used free shared buffers cached
Mem: 15G 1.5G 14G 1.0M 160M 1.0G
-/+ buffers/cache: 282M 15G
Swap: 1.0G 0B 1.0G

可以看到swap空间有1G,不过这是收缩了一次后的结果,最初的swap空间是16G……

free命令只显示了swap分区的大小,为了找到swap分区所在位置,需要具体查看一下分区情况。因为Ubuntu Server 14.04安装时默认使用了GPT分区形式,所以应该使用parted -l而不是fdisk -l来查看分区情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# parted -l

Model: ATA EEKSATA60G1702 (scsi)
Disk /dev/sda: 60.0GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number Start End Size File system Name Flags
1 1049kB 538MB 537MB fat32 EFI System Partition boot
2 538MB 794MB 256MB ext2
3 794MB 60.0GB 59.2GB lvm


Model: Linux device-mapper (linear) (dm)
Disk /dev/mapper/Xeon--vg-root: 58.2GB
Sector size (logical/physical): 512B/512B
Partition Table: loop

Number Start End Size File system Flags
1 0.00B 58.2GB 58.2GB ext4


Model: Linux device-mapper (linear) (dm)
Disk /dev/mapper/Xeon--vg-swap_1: 1065MB
Sector size (logical/physical): 512B/512B
Partition Table: loop

Number Start End Size File system Flags
1 0.00B 1065MB 1065MB linux-swap(v1)

从上面的输出结果中可以看到,硬盘上只有3个物理分区,前两个是系统启动引导时用的,可以忽略,主分区就只有一个,并没有单独为swap创建一个分区。Ubuntu系统在这里采用了LVM逻辑卷管理机制(Logical Volume Manager)进行磁盘空间管理,关于LVM可进一步阅读以下文章:

学习 Linux,101: 硬盘布局
逻辑卷管理
LVM Logical Volume

使用pvdisplay命令列出所有物理卷(PVs)属性:

1
2
3
4
5
6
7
8
9
10
11
12
# pvdisplay

--- Physical volume ---
PV Name /dev/sda3
VG Name Xeon-vg
PV Size 55.16 GiB / not usable 4.00 MiB
Allocatable yes (but full)
PE Size 4.00 MiB
Total PE 14120
Free PE 0
Allocated PE 14120
PV UUID lHbbtD-GhR7-5Ie9-OQnQ-9IYE-Y0cV-HDdZtZ

可以看到,只有一个物理卷/dev/sda3,再使用vgdisplay命令列出卷组(VGs)属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# vgdisplay

--- Volume group ---
VG Name Xeon-vg
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 6
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 2
Open LV 2
Max PV 0
Cur PV 1
Act PV 1
VG Size 55.16 GiB
PE Size 4.00 MiB
Total PE 14120
Alloc PE / Size 14120 / 55.16 GiB
Free PE / Size 0 / 0
VG UUID Wbc0FF-M7HR-Rzgf-4wf2-oNjB-J2KT-1Kwp0Z

唯一一个卷组的名称叫做Xeon-vgXeon是主机名),最后用lvdisplay命令列出所有逻辑卷(LVs)属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# lvdisplay

--- Logical volume ---
LV Path /dev/Xeon-vg/root
LV Name root
VG Name Xeon-vg
LV UUID TO99bO-91qT-Zqeu-SsJ0-jFMo-30Kn-oVtGqd
LV Write Access read/write
LV Creation host, time Xeon, 2017-02-27 07:01:36 +0800
LV Status available
# open 1
LV Size 54.16 GiB
Current LE 13866
Segments 2
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 252:0

--- Logical volume ---
LV Path /dev/Xeon-vg/swap_1
LV Name swap_1
VG Name Xeon-vg
LV UUID Ig7xvr-scZ3-Opqe-d1Ww-Z0aT-I4B1-9h2sD4
LV Write Access read/write
LV Creation host, time Xeon, 2017-02-27 07:01:36 +0800
LV Status available
# open 2
LV Size 1016.00 MiB
Current LE 254
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 252:1

此处划分了两个逻辑卷,分别是/dev/Xeon-vg/root/dev/Xeon-vg/swap_1,然而与parted -l的输出结果进行对比,会发现逻辑卷的名字并不相同,在parted -l的输出结果中使用的是/dev/mapper/Xeon--vg-root/dev/mapper/Xeon--vg-swap_1,查看这几个文件:

1
2
3
4
# ll /dev/Xeon-vg/

lrwxrwxrwx 1 root root 7 2月 27 21:09 root -> ../dm-0
lrwxrwxrwx 1 root root 7 2月 28 15:03 swap_1 -> ../dm-1
1
2
3
4
# ll /dev/mapper/

lrwxrwxrwx 1 root root 7 2月 27 21:09 Xeon--vg-root -> ../dm-0
lrwxrwxrwx 1 root root 7 2月 28 15:03 Xeon--vg-swap_1 -> ../dm-1

它们都通过符号链接指向了同一个地方:

1
2
3
4
# ll /dev | grep dm-

brw-rw---- 1 root disk 252, 0 2月 27 21:09 dm-0
brw-rw---- 1 root disk 252, 1 2月 28 15:03 dm-1

事实上这里用到的是Linux内核中的Device Mapper机制,设备名称dm就是Device Mapper之意。Device Mapper机制是LVM依赖的基础技术,用于实现物理设备到逻辑设备的映射,详细说明可进一步阅读以下文章:

Linux 内核中的 Device Mapper 机制
flashcache中应用device mapper机制
DOCKER基础技术:DEVICEMAPPER

另一个需要注意的问题是,尽管以上几个文件是通过符号链接联系起来的,不过它们并不等价,在使用lvm系列命令操作逻辑卷时,应该使用/dev/{VG}/{LV}这个路径,直接使用/dev/dm-*会出错。

通过以上操作,我们已经找到swap文件对应的逻辑卷位置了,下面就来减小其大小。

减小Swap分区

先用swapoff命令关闭交换分区:

1
# swapoff /dev/Xeon-vg/swap_1

检查下是否关闭成功了:

1
2
3
4
5
6
# free -h

total used free shared buffers cached
Mem: 15G 1.4G 14G 1.0M 176M 971M
-/+ buffers/cache: 299212 16104504
Swap: 0 0 0

可以看到swap分区的容量已经是0了,这时就可以通过lvreduce命令来收缩Swap_1这个逻辑卷的大小:

1
2
3
4
5
6
7
# lvreduce -L 512M /dev/Xeon-vg/swap_1 

WARNING: Reducing active logical volume to 512.00 MiB
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce swap_1? [y/n]: y
Reducing logical volume swap_1 to 512.00 MiB
Logical volume swap_1 successfully resized

-L 512M代表收缩至512M,更多用法可用man查询。之后要把新的逻辑卷重新设置为swap分区并用swapon命令开启之:

1
2
3
4
5
6
7
8
# mkswap /dev/Xeon-vg/swap_1

mkswap: /dev/Xeon-vg/swap_1: warning: don't erase bootbits sectors
on whole disk. Use -f to force.
Setting up swapspace version 1, size = 524284 KiB
no label, UUID=142b1c26-9e3f-45c4-afff-b0cce3c9448e

# swapon /dev/Xeon-vg/swap_1

最后检查下swap分区是否真的变小了:

1
2
3
4
5
6
# free -h

total used free shared buffers cached
Mem: 15G 1.4G 14G 1.0M 176M 971M
-/+ buffers/cache: 294M 15G
Swap: 511M 0B 511M

不过此时回收的空间成为了闲置的自由空间:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# vgdisplay

--- Volume group ---
VG Name Xeon-vg
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 7
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 2
Open LV 2
Max PV 0
Cur PV 1
Act PV 1
VG Size 55.16 GiB
PE Size 4.00 MiB
Total PE 14120
Alloc PE / Size 13994 / 54.66 GiB
Free PE / Size 126 / 504.00 MiB
VG UUID Wbc0FF-M7HR-Rzgf-4wf2-oNjB-J2KT-1Kwp0Z

注意其中的Free PE / Size,可以看到还有504M的未分配闲置空间,下一步就是要把这部分空间扩展到root逻辑卷中。

扩展root分区

对于Ext4文件系统,内核是支持在线扩容的,直接使用lvextend命令即可:

1
2
3
4
# lvextend -l +100%FREE /dev/Xeon-vg/root 

Extending logical volume root to 54.66 GiB
Logical volume root successfully resized

-l +100%FREE表示扩展所有剩余空间,需要注意的是,-l-L是不同的,-l的单位是所谓的logical extents,也就是上面vgdisplay命令显示出来的PE Size,这就是LVM中容量调整的一个基本单位;而-L的单位是传统的字节,-L选项不能搭配%100之类的形式使用。命令的详细用法还是参考man的说明。

逻辑卷的容量和文件系统的容量并没有直接关系,故最后还需要对文件系统进行在线扩容,对于Ext文件系统可使用resize2fs命令:

1
2
3
4
5
6
# resize2fs /dev/Xeon-vg/root 

resize2fs 1.42.9 (4-Feb-2014)
Filesystem at /dev/Xeon-vg/root is mounted on /; on-line resizing required
old_desc_blocks = 4, new_desc_blocks = 4
The filesystem on /dev/Xeon-vg/root is now 14327808 blocks long.

调整Swap分区交换策略

Linux系统并不是在内存全部使用完之后再使用swap空间的,内核会自动判断是否该使用swap空间,可以通过很多参数控制这一行为,可参考以下文章:

Tuning Virtual Memory

其中最重要的一个参数叫做swappiness,取值在0~100之间,表示的是内核使用swap空间的频率策略,值越大内核越倾向于使用交换空间。目前内存很大而swap空间很小,故可以尽量不去使用swap空间。要实现这一目的,将swapiness设置为0即可,这代表内核仅在内存快要用完时使用swap空间,具体解释可参考:

Swappiness

设置方法也很简单,使用sysctl命令可以临时修改:

1
# sysctl -w vm.swappiness=0

要永久修改的话,在/etc/sysctl.conf文件中添加vm.swappiness=0即可:

1
# echo vm.swappiness=0 >> /etc/sysctl.conf

除了用sysctl命令外,还可用以下方法查看当前swappiness的值:

1
# cat /proc/sys/vm/swappiness

参考资料:
linux基础命令介绍十二:磁盘与文件系统

文章目录
  1. 1. 定位swap分区
  2. 2. 减小Swap分区
  3. 3. 扩展root分区
  4. 4. 调整Swap分区交换策略