前言

今天咱们来聊聊Linux磁盘管理这个话题。说起磁盘管理,这可是每个运维工程师都绕不开的基本功。不管是新服务器上线、存储扩容,还是系统迁移,都离不开对磁盘的操作。

见过太多因为磁盘操作不当导致的"血案"了。数据丢失、系统崩溃、业务中断...这些惨痛的教训告诉我们,掌握正确的磁盘管理方法有多重要。

今天我就以Red Hat Enterprise Linux为例,从最基础的分区概念开始,到高级的逻辑卷管理,给大家来个全方位的磁盘管理实战指南。不管你是刚入门的新手,还是想要系统梳理知识的老手,相信都能从中收获满满。

Linux磁盘分区模式详解MBR分区模式(Master Boot Record)MBR是传统的分区模式,从DOS时代就开始使用,至今仍然广泛应用。

MBR的特点:

支持最大2TB的磁盘容量最多支持4个主分区如果需要更多分区,必须创建扩展分区和逻辑分区分区表存储在磁盘的第一个扇区(512字节)分区类型:

主分区(Primary Partition):可以直接安装操作系统,最多4个扩展分区(Extended Partition):不能直接使用,需要在其中创建逻辑分区逻辑分区(Logical Partition):在扩展分区中创建,数量不限我记得刚开始做运维的时候,经常被这个4个主分区的限制搞得头疼。有一次给服务器分区,需要分出系统分区、数据分区、日志分区、备份分区等好几个,结果发现主分区不够用,只能删掉重新规划,折腾了大半天。

GPT分区模式(GUID Partition Table)GPT是新一代的分区标准,解决了MBR的诸多限制。

GPT的优势:

支持超大容量磁盘(理论上可达18EB)支持128个主分区(在Linux下)分区表有备份,可靠性更高支持分区名称(最长36个字符)兼容UEFI启动什么时候选择GPT:

磁盘容量大于2TB需要超过4个分区使用UEFI启动的系统对数据可靠性要求较高的场景现在新采购的服务器,我基本都推荐使用GPT分区模式。虽然有些老的系统可能不兼容,但从长远来看,GPT是趋势。

常用磁盘分区命令详解fdisk命令 - MBR分区的老朋友fdisk是Linux下最经典的分区工具,主要用于MBR分区。

基本语法:

代码语言:javascript复制fdisk [选项] 设备名常用操作:

代码语言:javascript复制# 查看磁盘分区信息

fdisk -l

# 对指定磁盘进行分区操作

fdisk /dev/sdbfdisk交互命令:

p:显示分区表n:创建新分区d:删除分区t:改变分区类型w:保存并退出q:不保存退出实际操作示例:

代码语言:javascript复制[root@server ~]# fdisk /dev/sdb

Welcome to fdisk (util-linux 2.32.1).

Changes will remain in memory only, until you decide to write them.

Be careful before using the write command.

Command (m for help): n

Partition type:

p primary (0 primary, 0 extended, 4 free)

e extended (container for logical drives)

Select (default p): p

Partition number (1-4, default 1): 1

First sector (2048-20971519, default 2048):

Last sector, +sectors or +size{K,M,G,T,P} (2048-20971519, default 20971519): +5G

Created a new partition 1 of type 'Linux' and of size 5 GiB.

Command (m for help): w

The partition table has been altered!parted命令 - 现代分区的多面手parted是更现代的分区工具,支持MBR和GPT两种模式。

基本语法:

代码语言:javascript复制parted [选项] [设备名] [命令]常用操作:

代码语言:javascript复制# 查看所有磁盘信息

parted -l

# 进入交互模式

parted /dev/sdb

# 非交互模式创建分区

parted /dev/sdb mkpart primary 0% 50%parted交互命令:

print:显示分区表mklabel:创建分区表类型mkpart:创建分区rm:删除分区resizepart:调整分区大小GPT分区实例:

代码语言:javascript复制[root@server ~]# parted /dev/sdc

GNU Parted 3.2

Using /dev/sdc

Welcome to GNU Parted! Type 'help' to view a list of commands.

(parted) mklabel gpt

Warning: The existing disk label on /dev/sdc will be destroyed and all data on this disk will be lost. Do you want to continue?

Yes/No? yes

(parted) mkpart primary 0% 25%

(parted) mkpart primary 25% 50%

(parted) mkpart primary 50% 100%

(parted) print

Model: VMware Virtual disk (scsi)

Disk /dev/sdc: 21.5GB

Sector size (logical/physical): 512B/512B

Partition Table: gpt

Disk Flags:

Number Start End Size File system Name Flags

1 1049kB 5369MB 5368MB primary

2 5369MB 10.7GB 5368MB primary

3 10.7GB 21.5GB 10.7GB primary

(parted) quitgdisk命令 - GPT分区专家gdisk专门用于GPT分区,操作方式类似fdisk。

代码语言:javascript复制# 对GPT磁盘进行分区

gdisk /dev/sdblsblk命令 - 查看块设备信息这个命令用来查看系统中所有块设备的层次结构。

代码语言:javascript复制[root@server ~]# lsblk

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT

sda 8:0 0 20G 0 disk

├─sda1 8:1 0 1G 0 part /boot

└─sda2 8:2 0 19G 0 part

├─centos-root 253:0 0 17G 0 lvm /

└─centos-swap 253:1 0 2G 0 lvm [SWAP]

sdb 8:16 0 10G 0 disk

├─sdb1 8:17 0 5G 0 part

└─sdb2 8:18 0 5G 0 part 一块新磁盘的完整处理流程现在让我通过一个完整的实例,演示如何处理一块新添加的磁盘。

步骤1:识别新磁盘代码语言:javascript复制# 查看所有磁盘

lsblk

# 查看磁盘详细信息

fdisk -l

# 也可以查看/proc/partitions

cat /proc/partitions假设我们发现了一块新的10GB磁盘 /dev/sdb。

步骤2:选择分区模式并创建分区方案一:使用fdisk创建MBR分区

代码语言:javascript复制[root@server ~]# fdisk /dev/sdb

Command (m for help): n

Partition type:

p primary (0 primary, 0 extended, 4 free)

e extended (container for logical drives)

Select (default p): p

Partition number (1-4, default 1): 1

First sector (2048-20971519, default 2048):

Last sector, +sectors or +size{K,M,G,T,P}: +8G

Command (m for help): n

Partition type:

p primary (1 primary, 0 extended, 3 free)

e extended (container for logical drives)

Select (default p): p

Partition number (2-4, default 2): 2

First sector (16779264-20971519, default 16779264):

Last sector, +sectors or +size{K,M,G,T,P}:

Command (m for help): w方案二:使用parted创建GPT分区

代码语言:javascript复制[root@server ~]# parted /dev/sdb

(parted) mklabel gpt

(parted) mkpart data1 0% 80%

(parted) mkpart data2 80% 100%

(parted) quit步骤3:创建文件系统代码语言:javascript复制# 创建ext4文件系统

mkfs.ext4 /dev/sdb1

mkfs.ext4 /dev/sdb2

# 或者创建xfs文件系统(RHEL7+推荐)

mkfs.xfs /dev/sdb1

mkfs.xfs /dev/sdb2步骤4:创建挂载点并挂载代码语言:javascript复制# 创建挂载点

mkdir -p /data1 /data2

# 临时挂载

mount /dev/sdb1 /data1

mount /dev/sdb2 /data2

# 验证挂载

df -h步骤5:配置开机自动挂载代码语言:javascript复制# 获取UUID

blkid /dev/sdb1

blkid /dev/sdb2

# 编辑/etc/fstab

vim /etc/fstab

# 添加以下内容(UUID替换为实际值)

UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data1 ext4 defaults 0 2

UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data2 ext4 defaults 0 2

# 测试fstab配置

umount /data1 /data2

mount -a

df -h重要提醒: 在生产环境中,修改fstab后一定要用mount -a测试,确保配置正确。我见过好几次因为fstab配置错误导致系统无法启动的情况,最后只能进单用户模式修复。

逻辑卷管理(LVM)实战LVM(Logical Volume Manager)是Linux下的逻辑卷管理器,它提供了比传统分区更灵活的磁盘管理方式。在生产环境中,LVM几乎是标配,因为它可以动态调整容量,这对于业务系统来说太重要了。

LVM核心概念在开始实操之前,我们先理解几个核心概念:

PV(Physical Volume):物理卷,可以是整个磁盘或分区VG(Volume Group):卷组,由一个或多个PV组成的存储池LV(Logical Volume):逻辑卷,从VG中分配空间创建的虚拟分区PE(Physical Extent):物理扩展单元,PV的最小分配单位(默认4MB)LE(Logical Extent):逻辑扩展单元,LV的最小分配单位简单理解就是:把多个硬盘或分区(PV)组成一个大的存储池(VG),然后从这个池子里分配空间创建虚拟的分区(LV)。

创建LVM的完整流程让我通过一个实际案例来演示整个流程。假设我们有两块新硬盘/dev/sdb和/dev/sdc,需要创建LVM来管理。

步骤1:准备物理卷(PV)

代码语言:javascript复制# 首先查看可用磁盘

lsblk

# 创建物理卷(可以是整个磁盘或分区)

pvcreate /dev/sdb /dev/sdc

# 查看物理卷信息

pvdisplay

pvs输出示例:

代码语言:javascript复制[root@server ~]# pvcreate /dev/sdb /dev/sdc

Physical volume "/dev/sdb" successfully created.

Physical volume "/dev/sdc" successfully created.

[root@server ~]# pvs

PV VG Fmt Attr PSize PFree

/dev/sdb lvm2 --- 10.00g 10.00g

/dev/sdc lvm2 --- 10.00g 10.00g步骤2:创建卷组(VG)

代码语言:javascript复制# 创建卷组

vgcreate datavg /dev/sdb /dev/sdc

# 查看卷组信息

vgdisplay datavg

vgs输出示例:

代码语言:javascript复制[root@server ~]# vgcreate datavg /dev/sdb /dev/sdc

Volume group "datavg" successfully created

[root@server ~]# vgs

VG #PV #LV #SN Attr VSize VFree

datavg 2 0 0 wz--n- 19.99g 19.99g步骤3:创建逻辑卷(LV)

代码语言:javascript复制# 创建逻辑卷(指定大小)

lvcreate -L 10G -n datalv datavg

# 创建逻辑卷(使用百分比)

lvcreate -l 50%VG -n applv datavg

# 查看逻辑卷信息

lvdisplay

lvs输出示例:

代码语言:javascript复制[root@server ~]# lvcreate -L 10G -n datalv datavg

Logical volume "datalv" created.

[root@server ~]# lvcreate -l 50%FREE -n applv datavg

Logical volume "applv" created.

[root@server ~]# lvs

LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert

applv datavg -wi-a----- 5.00g

datalv datavg -wi-a----- 10.00g步骤4:创建文件系统并挂载

代码语言:javascript复制# 创建文件系统

mkfs.xfs /dev/datavg/datalv

mkfs.xfs /dev/datavg/applv

# 创建挂载点

mkdir -p /data /app

# 挂载

mount /dev/datavg/datalv /data

mount /dev/datavg/applv /app

# 验证

df -h步骤5:配置自动挂载

代码语言:javascript复制# 编辑/etc/fstab

vim /etc/fstab

# 添加以下内容

/dev/datavg/datalv /data xfs defaults 0 2

/dev/datavg/applv /app xfs defaults 0 2

# 测试配置

mount -aLVM容量调整实战LVM最大的优势就是可以动态调整容量。在我的运维生涯中,这个功能救过我无数次。

扩展逻辑卷容量场景: /data分区空间不足,需要扩容

代码语言:javascript复制# 1. 检查当前状态

df -h /data

lvs datavg

vgs datavg

# 2. 如果VG有足够空间,直接扩展LV

lvextend -L +5G /dev/datavg/datalv

# 或者扩展到指定大小

lvextend -L 15G /dev/datavg/datalv

# 3. 扩展文件系统

# 对于xfs文件系统

xfs_growfs /data

# 对于ext4文件系统

resize2fs /dev/datavg/datalv

# 4. 验证结果

df -h /data如果VG空间不足,需要先扩展VG:

代码语言:javascript复制# 1. 准备新的物理卷

pvcreate /dev/sdd

# 2. 扩展卷组

vgextend datavg /dev/sdd

# 3. 查看扩展后的VG

vgs datavg

# 4. 然后按上面步骤扩展LV

lvextend -L +10G /dev/datavg/datalv

xfs_growfs /data我记得有一次凌晨3点,数据库服务器的数据分区突然报警空间不足,业务马上要受影响。好在用的是LVM,我在5分钟内就完成了扩容,业务完全没有感知。如果是传统分区,那就麻烦大了。

缩减逻辑卷容量⚠️ 重要警告:缩减操作有数据丢失风险,务必先备份数据!

注意:xfs文件系统不支持缩减操作,只有ext系列文件系统支持。

代码语言:javascript复制# 1. 卸载文件系统

umount /app

# 2. 检查文件系统

e2fsck -f /dev/datavg/applv

# 3. 缩减文件系统(ext4)

resize2fs /dev/datavg/applv 3G

# 4. 缩减逻辑卷

lvreduce -L 3G /dev/datavg/applv

# 5. 重新挂载

mount /dev/datavg/applv /app在线扩展示例:

对于某些文件系统,可以实现在线扩展,不需要卸载:

代码语言:javascript复制# xfs文件系统在线扩展

lvextend -L +2G /dev/datavg/datalv

xfs_growfs /data

# ext4文件系统在线扩展

lvextend -L +2G /dev/datavg/applv

resize2fs /dev/datavg/applvLVM快照功能LVM还提供了快照功能,这在数据备份和测试环境中非常有用。

代码语言:javascript复制# 创建快照(快照大小根据变化量估算)

lvcreate -L 2G -s -n datalv_snap /dev/datavg/datalv

# 挂载快照

mkdir /data_snap

mount /dev/datavg/datalv_snap /data_snap

# 查看快照状态

lvs

# 删除快照

umount /data_snap

lvremove /dev/datavg/datalv_snap我经常在数据库升级前创建快照,如果升级失败可以快速回滚。不过要注意,快照会影响性能,不建议长期保留。

实际生产环境案例分析案例1:数据库服务器磁盘规划场景: 新上线一台MySQL数据库服务器,配置4块1TB SAS硬盘。

需求分析:

系统稳定性要求高数据安全性要求高需要考虑后期扩容I/O性能要求较高规划方案:

代码语言:javascript复制# 磁盘1-2:系统盘,做RAID1镜像

# /dev/sda 系统盘分区规划

/dev/sda1 /boot 1G ext4

/dev/sda2 / 30G xfs

/dev/sda3 /var/log 10G xfs

/dev/sda4 swap 16G swap

# 磁盘3-4:数据盘,使用LVM管理

pvcreate /dev/sdc /dev/sdd

vgcreate mysql_vg /dev/sdc /dev/sdd

# 创建逻辑卷

lvcreate -L 1500G -n mysql_data mysql_vg # 数据目录

lvcreate -L 200G -n mysql_log mysql_vg # 日志目录

lvcreate -L 100G -n mysql_backup mysql_vg # 备份目录

lvcreate -L 50G -n mysql_temp mysql_vg # 临时目录为什么这样规划:

系统盘使用RAID1保证可靠性数据盘使用LVM方便后期扩容分离数据、日志、备份,提高I/O性能预留部分空间用于快照和临时扩容案例2:Web服务器存储优化场景: Web服务器需要存储大量静态文件,访问频繁,需要优化存储结构。

原始状况:

单块2TB磁盘,使用传统分区网站文件、日志、缓存都在一个分区经常出现空间不足问题优化方案:

代码语言:javascript复制# 添加新磁盘,使用LVM重新规划

pvcreate /dev/sdb /dev/sdc

vgcreate web_vg /dev/sdb /dev/sdc

# 创建专用逻辑卷

lvcreate -L 1T -n web_files web_vg # 网站文件

lvcreate -L 500G -n web_logs web_vg # 访问日志

lvcreate -L 200G -n web_cache web_vg # 缓存文件

lvcreate -L 100G -n web_backup web_vg # 备份文件

# 创建文件系统

mkfs.xfs /dev/web_vg/web_files

mkfs.xfs /dev/web_vg/web_logs

mkfs.xfs /dev/web_vg/web_cache

mkfs.xfs /dev/web_vg/web_backup

# 挂载到相应目录

mount /dev/web_vg/web_files /var/www/html

mount /dev/web_vg/web_logs /var/log/httpd

mount /dev/web_vg/web_cache /var/cache/nginx

mount /dev/web_vg/web_backup /backup优化效果:

不同类型文件分离存储,I/O性能提升可以针对不同分区设置不同的挂载参数扩容更加灵活,按需分配空间案例3:在线扩容实战场景: 电商网站图片存储空间告急,需要紧急扩容,不能影响业务。

告警信息:

代码语言:javascript复制[root@web01 ~]# df -h

Filesystem Size Used Avail Use% Mounted on

/dev/mapper/web_vg-images_lv 50G 47G 1.9G 97% /var/www/images扩容步骤:

代码语言:javascript复制# 1. 检查VG剩余空间

vgs web_vg

VG #PV #LV #SN Attr VSize VFree

web_vg 2 4 0 wz--n- 1.82t 200.00g

# 2. 在线扩展逻辑卷

lvextend -L +20G /dev/web_vg/images_lv

Size of logical volume web_vg/images_lv changed from 50.00 GiB to 70.00 GiB.

Logical volume web_vg/images_lv successfully resized.

# 3. 在线扩展文件系统

xfs_growfs /var/www/images

meta-data=/dev/mapper/web_vg-images_lv isize=512 agcount=4, agsize=3276800 blks

= sectsz=512 attr=2, projid32bit=1

= crc=1 finobt=0 spinodes=0

data = bsize=4096 blocks=13107200, imaxpct=25

= sunit=0 swidth=0 blks

naming =version 2 bsize=4096 ascii-ci=0 ftype=1

log =internal bsize=4096 blocks=6400, version=2

= sectsz=512 sunit=0 blks, lazy-count=1

realtime =none extsz=4096 blocks=0, rtextents=0

data blocks changed from 13107200 to 18350080

# 4. 验证结果

df -h /var/www/images

Filesystem Size Used Avail Use% Mounted on

/dev/mapper/web_vg-images_lv 70G 47G 24G 67% /var/www/images整个过程不到2分钟,业务完全无感知。这就是LVM的强大之处!

最佳实践与注意事项磁盘分区最佳实践经过多年的生产环境实践,我总结了以下最佳实践:

1. 合理规划分区大小

代码语言:javascript复制# 推荐的分区规划

/boot 1GB # 引导分区,1GB足够

/ 30-50GB # 根分区,不要太大也不要太小

/var 20GB+ # 变量数据,日志文件存放

/var/log 单独分区 # 防止日志填满系统盘

/tmp 单独分区 # 临时文件,可设置noexec参数

swap 内存1-2倍 # 物理内存大于8GB时可以等于内存大小2. 选择合适的文件系统

代码语言:javascript复制# 不同场景的文件系统选择

系统分区: xfs(RHEL7+默认)

数据分区: xfs(大文件性能好)

日志分区: ext4(小文件性能好)

临时分区: tmpfs(内存文件系统)3. 使用LVM管理数据盘

代码语言:javascript复制# 数据盘强烈推荐使用LVM

# 系统盘可以不用LVM,保持简单

# 为VG预留10-20%的空间用于快照和扩容

vgcreate -s 32M datavg /dev/sdb /dev/sdc # 大容量使用大PE安全操作建议1. 操作前必须备份

代码语言:javascript复制# 备份分区表

sfdisk -d /dev/sda > /root/sda_partition_backup.txt

dd if=/dev/sda of=/root/mbr_backup.img bs=512 count=1

# 备份重要数据

tar -czf /backup/data_backup_$(date +%Y%m%d).tar.gz /important/data

# 备份LVM配置

vgcfgbackup2. 使用UUID而不是设备名

代码语言:javascript复制# /etc/fstab中推荐使用UUID

UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data xfs defaults 0 2

# 而不是使用设备名(可能会变化)

/dev/sdb1 /data xfs defaults 0 23. 测试配置

代码语言:javascript复制# 修改/etc/fstab后必须测试

mount -a

echo $? # 返回0表示成功

# 检查挂载状态

df -h

findmnt4. 设置合适的挂载参数

代码语言:javascript复制# 针对不同用途设置不同参数

/dev/datavg/web_lv /var/www xfs defaults,noatime 0 2 # Web文件,禁用访问时间更新

/dev/datavg/log_lv /var/log xfs defaults,nodev,nosuid 0 2 # 日志分区,安全参数

/dev/datavg/tmp_lv /tmp xfs defaults,nodev,nosuid,noexec 0 2 # 临时分区,禁止执行性能优化建议1. 分区对齐

代码语言:javascript复制# 使用parted创建分区时确保对齐

parted /dev/sdb mkpart primary 2048s 100%

# 检查分区对齐

parted /dev/sdb align-check optimal 12. 选择合适的PE大小

代码语言:javascript复制# 根据VG大小选择PE大小

小于16GB: 4MB(默认)

16GB-256GB: 8MB

256GB-1TB: 16MB

大于1TB: 32MB

vgcreate -s 32M large_vg /dev/sdb3. I/O调度器优化

代码语言:javascript复制# 查看当前调度器

cat /sys/block/sda/queue/scheduler

# SSD使用noop或deadline

echo noop > /sys/block/sda/queue/scheduler

# 机械硬盘使用cfq

echo cfq > /sys/block/sdb/queue/scheduler

# 永久设置(添加到/etc/rc.local)

echo 'echo noop > /sys/block/sda/queue/scheduler' >> /etc/rc.local故障排除与恢复常见问题及解决方案在运维工作中,磁盘相关的故障是最常见的,下面分享一些实用的排查和恢复方法。

问题1:分区表损坏

症状:系统无法识别分区,fdisk -l显示异常

代码语言:javascript复制# 使用testdisk恢复分区表

yum install testdisk

testdisk /dev/sda

# 或者使用备份恢复

sfdisk /dev/sda < /root/sda_partition_backup.txt

# GPT分区表修复

gdisk /dev/sda

# 在gdisk中使用 'r' 进入恢复模式,然后使用 'c' 修复问题2:LVM元数据损坏

症状:vgs、lvs命令报错,无法激活卷组

代码语言:javascript复制# 扫描并修复

pvscan --cache

vgscan --mknodes

lvscan

# 强制激活(谨慎使用)

vgchange -ay --partial datavg

# 从备份恢复LVM配置

vgcfgrestore datavg问题3:文件系统损坏

症状:无法挂载,提示文件系统错误

代码语言:javascript复制# ext4文件系统检查修复

umount /dev/sda1

e2fsck -f /dev/sda1

e2fsck -y /dev/sda1 # 自动回答yes

# xfs文件系统检查修复

umount /dev/sda1

xfs_repair /dev/sda1

xfs_repair -L /dev/sda1 # 强制修复,可能丢失数据问题4:/etc/fstab配置错误导致启动失败(敲黑板,这个非常常见)

这是我遇到过最多的问题之一,解决方法:

代码语言:javascript复制# 1. 进入单用户模式或救援模式

# 2. 重新挂载根分区为可写

mount -o remount,rw /

# 3. 修复/etc/fstab

vim /etc/fstab

# 注释掉有问题的行或修正配置

# 4. 测试配置

mount -a

# 5. 重启系统

reboot数据恢复技巧当发生严重的数据丢失时,可以尝试以下恢复方法:

1. 使用ddrescue恢复数据

代码语言:javascript复制# 安装ddrescue

yum install ddrescue

# 创建磁盘镜像(先救数据,后分析)

ddrescue -d -r3 /dev/sda /backup/sda_image.img /backup/sda_recovery.log

# 在镜像上进行恢复操作

losetup /dev/loop0 /backup/sda_image.img2. 使用photorec恢复文件

代码语言:javascript复制# photorec是testdisk套件的一部分

photorec /dev/sda

# 或者在镜像上恢复

photorec /backup/sda_image.img3. 恢复ext4删除的文件

代码语言:javascript复制# 使用extundelete恢复

yum install extundelete

# 恢复所有删除的文件

extundelete /dev/sda1 --restore-all

# 恢复特定文件

extundelete /dev/sda1 --restore-file /path/to/file监控与预警系统建立完善的监控系统可以提前发现问题:

1. 磁盘空间监控脚本

代码语言:javascript复制#!/bin/bash

# disk_monitor.sh

THRESHOLD=85

EMAIL="admin@company.com"

df -h | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{print $5 " " $1}' | while read output;

do

usage=$(echo $output | awk '{print $1}' | sed 's/%//g')

partition=$(echo $output | awk '{print $2}')

if [ $usage -ge $THRESHOLD ]; then

message="Warning: Disk usage on $partition is ${usage}%"

echo $message

# 发送邮件告警

echo $message | mail -s "Disk Space Alert" $EMAIL

# 记录日志

logger "DISK_ALERT: $message"

fi

done2. LVM状态监控

代码语言:javascript复制#!/bin/bash

# lvm_monitor.sh

# 检查VG状态

vgs --noheadings -o vg_name,vg_attr | while read vg_name vg_attr; do

if [[ $vg_attr != *"w"* ]]; then

echo "Warning: VG $vg_name is not writable"

logger "LVM_ALERT: VG $vg_name status abnormal: $vg_attr"

fi

done

# 检查LV状态

lvs --noheadings -o lv_name,vg_name,lv_attr | while read lv_name vg_name lv_attr; do

if [[ $lv_attr != *"a"* ]]; then

echo "Warning: LV $vg_name/$lv_name is not active"

logger "LVM_ALERT: LV $vg_name/$lv_name status abnormal: $lv_attr"

fi

done3. 设置定时任务

代码语言:javascript复制# 添加到crontab

crontab -e

# 每10分钟检查磁盘空间

*/10 * * * * /root/scripts/disk_monitor.sh

# 每小时检查LVM状态

0 * * * * /root/scripts/lvm_monitor.sh

# 每天备份分区表和LVM配置

0 2 * * * sfdisk -d /dev/sda > /backup/sda_partition_$(date +\%Y\%m\%d).txt

0 2 * * * vgcfgbackup自动化运维脚本为了提高工作效率,我编写了一些实用的自动化脚本:

磁盘初始化脚本代码语言:javascript复制#!/bin/bash

# disk_init.sh - 自动初始化新磁盘为LVM

# 检查参数

if [ $# -lt 2 ]; then

echo "Usage: $0 [lv_name] [lv_size]"

echo "Example: $0 /dev/sdb datavg datalv 100G"

exit 1

fi

DISK=$1

VG_NAME=$2

LV_NAME=${3:-"datalv"}

LV_SIZE=${4:-"100%FREE"}

# 安全检查

if ! lsblk $DISK &>/dev/null; then

echo "Error: Disk $DISK not found"

exit 1

fi

echo "Warning: This will destroy all data on $DISK"

echo "VG Name: $VG_NAME"

echo "LV Name: $LV_NAME"

echo "LV Size: $LV_SIZE"

read -p "Continue? (yes/no): " confirm

if [ "$confirm" != "yes" ]; then

echo "Operation cancelled"

exit 0

fi

# 创建PV

echo "Creating Physical Volume..."

pvcreate $DISK

if [ $? -ne 0 ]; then

echo "Error: Failed to create PV"

exit 1

fi

# 创建或扩展VG

if vgs $VG_NAME &>/dev/null; then

echo "Extending existing Volume Group..."

vgextend $VG_NAME $DISK

else

echo "Creating Volume Group..."

vgcreate $VG_NAME $DISK

fi

if [ $? -ne 0 ]; then

echo "Error: Failed to create/extend VG"

exit 1

fi

# 创建LV

echo "Creating Logical Volume..."

lvcreate -n $LV_NAME -l $LV_SIZE $VG_NAME

if [ $? -ne 0 ]; then

echo "Error: Failed to create LV"

exit 1

fi

# 创建文件系统

echo "Creating XFS filesystem..."

mkfs.xfs /dev/$VG_NAME/$LV_NAME

if [ $? -ne 0 ]; then

echo "Error: Failed to create filesystem"

exit 1

fi

echo "Disk initialization completed successfully!"

echo "Device: /dev/$VG_NAME/$LV_NAME"

echo "Next steps:"

echo "1. Create mount point: mkdir /your/mount/point"

echo "2. Mount: mount /dev/$VG_NAME/$LV_NAME /your/mount/point"

echo "3. Add to /etc/fstab for persistent mounting"LVM扩容脚本代码语言:javascript复制#!/bin/bash

# lvm_extend.sh - 自动扩展LVM逻辑卷

if [ $# -ne 3 ]; then

echo "Usage: $0 "

echo "Example: $0 /dev/datavg/datalv +10G /data"

exit 1

fi

LV_PATH=$1

SIZE=$2

MOUNT_POINT=$3

# 检查LV是否存在

if ! lvs $LV_PATH &>/dev/null; then

echo "Error: Logical Volume $LV_PATH not found"

exit 1

fi

# 检查挂载点

if ! mountpoint -q $MOUNT_POINT; then

echo "Error: $MOUNT_POINT is not a mount point"

exit 1

fi

# 获取文件系统类型

FS_TYPE=$(findmnt -n -o FSTYPE $MOUNT_POINT)

echo "Extending Logical Volume $LV_PATH by $SIZE"

echo "Mount Point: $MOUNT_POINT"

echo "Filesystem: $FS_TYPE"

# 扩展LV

echo "Extending Logical Volume..."

lvextend -L $SIZE $LV_PATH

if [ $? -ne 0 ]; then

echo "Error: Failed to extend LV"

exit 1

fi

# 扩展文件系统

echo "Extending filesystem..."

case $FS_TYPE in

xfs)

xfs_growfs $MOUNT_POINT

;;

ext4|ext3|ext2)

resize2fs $LV_PATH

;;

*)

echo "Warning: Unsupported filesystem type: $FS_TYPE"

echo "Please manually extend the filesystem"

exit 1

;;

esac

if [ $? -eq 0 ]; then

echo "Extension completed successfully!"

echo "New size:"

df -h $MOUNT_POINT

else

echo "Error: Failed to extend filesystem"

exit 1

fi系统健康检查脚本代码语言:javascript复制#!/bin/bash

# system_health_check.sh - 系统存储健康检查

echo "=== System Storage Health Check ==="

echo "Date: $(date)"

echo

# 检查磁盘空间

echo "=== Disk Space Usage ==="

df -h | grep -vE '^Filesystem|tmpfs|udev'

echo

# 检查磁盘I/O

echo "=== Disk I/O Statistics ==="

iostat -x 1 1 | tail -n +4

echo

# 检查LVM状态

if command -v vgs &>/dev/null; then

echo "=== LVM Volume Groups ==="

vgs

echo

echo "=== LVM Logical Volumes ==="

lvs

echo

echo "=== LVM Physical Volumes ==="

pvs

echo

fi

# 检查RAID状态(如果有)

if [ -f /proc/mdstat ]; then

echo "=== Software RAID Status ==="

cat /proc/mdstat

echo

fi

# 检查挂载状态

echo "=== Mount Status ==="

findmnt -D

echo

# 检查文件系统错误

echo "=== Filesystem Errors Check ==="

dmesg | grep -i "error\|fail\|corrupt" | grep -i "ext\|xfs\|filesystem" | tail -10

echo

# 检查SMART状态(如果smartctl可用)

if command -v smartctl &>/dev/null; then

echo "=== SMART Status ==="

for disk in $(lsblk -d -n -o NAME | grep -E '^sd[a-z]$'); do

echo "Disk: /dev/$disk"

smartctl -H /dev/$disk 2>/dev/null | grep -E "SMART overall-health|result"

done

echo

fi

echo "=== Health Check Completed ==="存储技术发展趋势随着云计算和容器技术的发展,传统的存储管理方式也在不断演进。作为运维人员,我们需要了解这些新技术:

1. 容器存储

代码语言:javascript复制# Docker卷管理

docker volume create mydata

docker run -v mydata:/data nginx

# Kubernetes持久卷

apiVersion: v1

kind: PersistentVolume

metadata:

name: pv-data

spec:

capacity:

storage: 100Gi

accessModes:

- ReadWriteOnce

hostPath:

path: /data2. 软件定义存储

代码语言:javascript复制# Ceph分布式存储

ceph osd pool create mypool 128

rbd create --size 10240 mypool/mydisk

# GlusterFS分布式文件系统

gluster volume create myvol replica 2 server1:/brick1 server2:/brick1

gluster volume start myvol3. 云存储集成

代码语言:javascript复制# 挂载阿里云OSS

ossfs mybucket /mnt/oss -ourl=http://oss-cn-hangzhou.aliyuncs.com

# 挂载AWS S3

s3fs mybucket /mnt/s3 -o passwd_file=/etc/passwd-s3fs性能调优深入对于高并发、大数据量的应用,存储性能调优变得尤为重要:

1. I/O调度器优化

代码语言:javascript复制# 查看和设置I/O调度器

cat /sys/block/sda/queue/scheduler

echo mq-deadline > /sys/block/sda/queue/scheduler

# 针对不同存储类型的推荐设置

# SSD: none 或 mq-deadline

# 机械硬盘: mq-deadline 或 bfq

# NVMe: none2. 文件系统参数调优

代码语言:javascript复制# XFS调优参数

mount -o noatime,largeio,inode64,swalloc /dev/datavg/datalv /data

# Ext4调优参数

mount -o noatime,data=writeback,barrier=0,nobh /dev/datavg/datalv /data3. LVM性能优化

代码语言:javascript复制# 使用适当的PE大小

vgcreate -s 32M large_vg /dev/sdb

# 条带化提升性能

lvcreate -L 100G -i 2 -I 64 -n striped_lv datavg

# 使用SSD作为缓存

lvcreate -L 20G -n cache_pool datavg /dev/nvme0n1

lvconvert --type cache-pool datavg/cache_pool

lvconvert --type cache --cachepool datavg/cache_pool datavg/data_lv企业级存储方案在大型企业环境中,存储架构通常更加复杂:

1. 多路径存储

代码语言:javascript复制# 安装multipath

yum install device-mapper-multipath

# 配置multipath

mpathconf --enable --with_multipathd y

# 查看多路径设备

multipath -ll2. 存储复制和同步

代码语言:javascript复制# 使用rsync同步数据

rsync -avz --progress /data/ backup-server:/backup/data/

# 使用DRBD实现块级复制

drbdadm create-md r0

drbdadm up r0

drbdadm primary --force r03. 快照策略

代码语言:javascript复制#!/bin/bash

# snapshot_backup.sh - 自动快照备份脚本

VG_NAME="datavg"

LV_NAME="datalv"

SNAP_NAME="snap_$(date +%Y%m%d_%H%M%S)"

BACKUP_DIR="/backup"

# 创建快照

lvcreate -L 10G -s -n $SNAP_NAME /dev/$VG_NAME/$LV_NAME

# 挂载快照

mkdir -p /mnt/$SNAP_NAME

mount /dev/$VG_NAME/$SNAP_NAME /mnt/$SNAP_NAME

# 备份数据

tar -czf $BACKUP_DIR/backup_$(date +%Y%m%d).tar.gz -C /mnt/$SNAP_NAME .

# 清理快照

umount /mnt/$SNAP_NAME

lvremove -f /dev/$VG_NAME/$SNAP_NAME

rmdir /mnt/$SNAP_NAME

echo "Backup completed: $BACKUP_DIR/backup_$(date +%Y%m%d).tar.gz"故障预防与应急响应1. 预防性维护

代码语言:javascript复制#!/bin/bash

# preventive_maintenance.sh

# 检查磁盘健康状态

for disk in $(lsblk -d -n -o NAME | grep -E '^sd[a-z]$'); do

echo "Checking /dev/$disk..."

smartctl -t short /dev/$disk

sleep 60

smartctl -l selftest /dev/$disk | head -10

done

# 检查文件系统

for fs in $(findmnt -n -o TARGET -t xfs,ext4); do

echo "Checking filesystem: $fs"

if [[ $fs == *"xfs"* ]]; then

xfs_info $fs > /dev/null

else

tune2fs -l $(findmnt -n -o SOURCE $fs) > /dev/null

fi

done2. 应急响应预案

代码语言:javascript复制#!/bin/bash

# emergency_response.sh

case $1 in

"disk_full")

echo "Disk full emergency response..."

# 清理临时文件

find /tmp -type f -mtime +7 -delete

find /var/log -name "*.log" -mtime +30 -delete

# 压缩日志文件

find /var/log -name "*.log" -size +100M -exec gzip {} \;

;;

"lvm_failure")

echo "LVM failure emergency response..."

# 尝试激活VG

vgchange -ay

# 扫描并修复

pvscan --cache

vgscan --mknodes

;;

"filesystem_error")

echo "Filesystem error emergency response..."

# 只读挂载保护数据

mount -o remount,ro /problematic/mount

# 记录错误信息

dmesg | tail -50 > /var/log/emergency_$(date +%Y%m%d_%H%M%S).log

;;

esac监控与告警进阶1. 集成Prometheus监控

代码语言:javascript复制# prometheus.yml配置片段

- job_name: 'node-exporter'

static_configs:

- targets: ['localhost:9100']

# 磁盘空间告警规则

groups:

- name: disk

rules:

- alert: DiskSpaceHigh

expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < 15

for: 5m

labels:

severity: warning

annotations:

summary: "Disk space usage is above 85%"2. 自定义监控指标

代码语言:javascript复制#!/bin/bash

# custom_metrics.sh

# 输出Prometheus格式的指标

echo "# HELP lvm_vg_free_bytes Free bytes in volume group"

echo "# TYPE lvm_vg_free_bytes gauge"

vgs --noheadings --units b -o vg_name,vg_free | while read vg_name vg_free; do

vg_free_bytes=$(echo $vg_free | sed 's/B//')

echo "lvm_vg_free_bytes{vg_name=\"$vg_name\"} $vg_free_bytes"

done写在最后经过这么多年的运维工作,我深深体会到存储管理的重要性。每一次磁盘故障、每一次数据恢复、每一次性能优化,都是宝贵的经验积累。

记得刚开始做运维的时候,因为对LVM不熟悉,在扩容时操作失误导致了数据丢失,那一夜的通宵达旦和焦虑至今记忆犹新。从那以后,我就告诉自己:任何存储操作都要三思而后行,备份永远是第一位的。

现在的存储技术发展很快,从传统的本地存储到分布式存储,从物理机到虚拟化再到容器化,技术在变,但基础的原理和思维方式是不变的。希望大家能够:

打好基础:扎实掌握分区、文件系统、LVM等基础知识注重实践:多在测试环境练习,积累实际操作经验 保持学习:关注新技术发展,但不要忘记基础建立规范:制定标准的操作流程和应急预案分享交流:多与同行交流经验,共同提高运维这条路不容易,但很有意思。每解决一个问题,每优化一个性能瓶颈,每成功恢复一次故障,都会让我们成长。希望这篇文章能够帮助到正在这条路上奋斗的朋友们。

技术的路很长,我们一起走。如果你在工作中遇到存储相关的问题,或者有什么好的经验想要分享,都欢迎留言讨论。让我们在交流中共同进步,在实践中不断成长!

觉得这篇文章有用的话,别忘了点赞、转发、收藏三连击!你的支持是我持续分享的动力。关注@运维躬行录,我会持续分享更多实用的运维技术和经验,让我们一起在运维的道路上精进技艺,共同成长!