磁盘、文件系统与挂载自动化
检查块设备、管理 fstab 条目,并安全地编写 LVM 和挂载操作脚本。
磁盘、文件系统与挂载自动化 是 CoddyKit 上的免费 Linux Command Line & Bash Scripting Mastery 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Linux Command Line & Bash Scripting Mastery 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Linux Command Line & Bash Scripting Mastery 课程共包含 4 节课。
使用 lsblk 和 fdisk 理解块设备
在自动化磁盘操作之前,您必须能够检查系统中有哪些块设备。lsblk 和 fdisk -l 是两个必备工具。
lsblk— 以树状格式列出块设备,显示设备名称、大小、挂载点和类型(disk、part、lvm)fdisk -l— 显示分区表和扇区详细信息(需要 root 权限)blkid— 输出每个块设备的 UUID 和文件系统类型
在脚本中,您经常需要解析这些输出,以检测可用磁盘、检查分区是否已格式化,或在挂载前确定其 UUID。
#!/usr/bin/env bash
# Inspect all block devices and their UUIDs
set -euo pipefail
echo '=== Block Device Tree ==='
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,UUID
echo ''
echo '=== Partition Table Details ==='
sudo fdisk -l 2>/dev/null | grep -E '^Disk |^/dev/'
echo ''
echo '=== UUID Lookup via blkid ==='
sudo blkid | awk -F: '{print $1}' | while read -r dev; do
uuid=$(sudo blkid -s UUID -o value "$dev" 2>/dev/null || echo 'N/A')
fstype=$(sudo blkid -s TYPE -o value "$dev" 2>/dev/null || echo 'unknown')
printf '%-20s UUID=%-38s TYPE=%s\n' "$dev" "$uuid" "$fstype"
done使用 df 和 du 检查磁盘空间
df 和 du 是报告文件系统和目录使用情况的主要工具。在系统管理脚本中,您可以使用它们触发警报、强制执行配额,或决定何时分配更多空间。
df -h— 以人类易读的格式显示所有已挂载文件系统的使用情况df -BG— 以 GB 为单位输出,便于进行一致的数值解析du -sh /path— 汇总显示指定目录的大小du -d 1 /var— 显示一层深度的详细使用情况(有助于找出占用空间较大的子目录)
df 输出中的已使用百分比列通常会被解析,以便在监控脚本中触发磁盘空间耗尽警报。
#!/usr/bin/env bash
# Alert if any mounted filesystem exceeds a usage threshold
set -euo pipefail
THRESHOLD=80 # percent
echo 'Checking filesystem usage...'
df -h --output=source,pcent,target | tail -n +2 | while IFS= read -r line; do
device=$(awk '{print $1}' <<< "$line")
pct=$(awk '{print $2}' <<< "$line" | tr -d '%')
mount=$(awk '{print $3}' <<< "$line")
# Skip pseudo filesystems
[[ "$device" == tmpfs* || "$device" == devtmpfs* ]] && continue
if (( pct >= THRESHOLD )); then
echo "WARNING: $device mounted at $mount is ${pct}% full" >&2
else
echo "OK: $device at $mount is ${pct}% used"
fi
done读取并解析 /etc/fstab
/etc/fstab 是静态文件系统表,用于定义哪些设备会在启动时挂载、挂载到什么路径以及使用哪些选项。每行包含六个字段:
- 设备 — UUID=...、LABEL=... 或 /dev/sdX
- 挂载点 — 目录路径
- 文件系统类型 — ext4、xfs、nfs、tmpfs 等
- 选项 — defaults、ro、noexec、nofail 等
- Dump — 0 或 1(备份标志)
- Pass — 0、1 或 2(fsck 顺序)
用于添加或验证 fstab 条目的脚本必须妥善处理注释(以 # 开头的行)和空行。请始终优先使用 UUID 而不是设备名称,以应对重启后设备顺序可能发生变化的情况。
#!/usr/bin/env bash
# Parse /etc/fstab and display non-comment entries in a readable table
set -euo pipefail
FSTAB=/etc/fstab
printf '%-40s %-20s %-10s %s\n' 'DEVICE' 'MOUNTPOINT' 'FSTYPE' 'OPTIONS'
printf '%s\n' '-------------------------------------------------------------------------------------'
while IFS= read -r line; do
# Skip blank lines and comments
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue
read -r device mountpt fstype options _dump _pass <<< "$line"
printf '%-40s %-20s %-10s %s\n' "$device" "$mountpt" "$fstype" "$options"
done < "$FSTAB"安全地添加 fstab 条目
手动编辑 /etc/fstab 容易出错。错误的条目可能会导致系统无法启动。安全的自动化脚本应当做到:
- 追加之前检查条目是否已经存在(幂等性)
- 进行任何修改之前备份原始文件
- 使用 UUID,而不是设备路径
- 将
nofail添加到挂载选项中,这样磁盘缺失时不会阻止系统启动 - 以试运行方式运行
mount -a,或执行测试挂载,在重启前进行验证
写入条目后,始终使用 findmnt --verify 进行验证(现代 systemd 发行版通常提供此命令),以便立即发现语法错误。
#!/usr/bin/env bash
# Safely append a new entry to /etc/fstab (idempotent)
set -euo pipefail
DEVICE_PATH='/dev/sdb1'
MOUNTPOINT='/mnt/data'
FSTYPE='ext4'
OPTIONS='defaults,nofail'
FSTAB='/etc/fstab'
# Resolve UUID for stable identification
UUID=$(sudo blkid -s UUID -o value "$DEVICE_PATH")
if [[ -z "$UUID" ]]; then
echo "ERROR: Could not resolve UUID for $DEVICE_PATH" >&2
exit 1
fi
ENTRY="UUID=$UUID $MOUNTPOINT $FSTYPE $OPTIONS 0 2"
# Idempotency: skip if UUID already referenced in fstab
if grep -qsF "UUID=$UUID" "$FSTAB"; then
echo "INFO: fstab already contains UUID=$UUID — skipping."
exit 0
fi
# Backup
cp -p "$FSTAB" "${FSTAB}.bak.$(date +%Y%m%d%H%M%S)"
# Create mountpoint if needed
sudo mkdir -p "$MOUNTPOINT"
# Append entry
echo "$ENTRY" | sudo tee -a "$FSTAB" > /dev/null
echo "INFO: Added: $ENTRY"
# Validate
sudo findmnt --verify --verbose || echo 'WARNING: findmnt verify reported issues'在脚本中挂载和卸载文件系统
mount 和 umount 命令本身很直接,但脚本必须处理边界情况:
- 设备可能已经挂载——再次挂载会失败;请使用
findmnt或mountpoint检查 - 挂载点可能处于忙碌状态(存在打开的文件)——
umount会失败;请使用lsof +D /mnt/target查找相关进程 - 使用
mount -o remount,ro /mnt/data可以在不卸载的情况下切换为只读模式 - 最后再使用
umount -l /mnt/data(延迟卸载)——它会解除命名空间的连接,但会等待引用关闭
在自动化操作中,始终检查 mount 的退出代码,并使用 logger 将失败记录到 syslog。
#!/usr/bin/env bash
# Mount a device only if not already mounted; log outcome
set -euo pipefail
DEVICE='/dev/sdb1'
MOUNTPOINT='/mnt/data'
log() { logger -t disk-mount "$*"; echo "[$(date '+%F %T')] $*"; }
# Check if already mounted
if mountpoint -q "$MOUNTPOINT"; then
log "INFO: $MOUNTPOINT is already mounted — nothing to do."
exit 0
fi
# Ensure mountpoint directory exists
sudo mkdir -p "$MOUNTPOINT"
# Attempt mount
if sudo mount "$DEVICE" "$MOUNTPOINT"; then
log "OK: Mounted $DEVICE at $MOUNTPOINT"
else
log "ERROR: Failed to mount $DEVICE at $MOUNTPOINT"
exit 1
fi
# Show what is now mounted there
df -h "$MOUNTPOINT"LVM 简介:物理卷、卷组和逻辑卷
LVM(逻辑卷管理器)在原始块设备与文件系统之间增加了一个灵活的抽象层。其三级层次结构如下:
- 物理卷(PV)——使用
pvcreate初始化的原始磁盘或分区 - 卷组(VG)——使用
vgcreate将一个或多个 PV 汇集到一起 - 逻辑卷(LV)——使用
lvcreate从 VG 中划分出的虚拟分区;您可以对它进行格式化和挂载
其主要优势在于:您可以在在线状态下扩展 LV,无需卸载;还可以向 VG 添加新磁盘,而无需重新格式化。这使 LVM 成为生产环境存储自动化不可或缺的工具。
检查命令包括:pvs、vgs、lvs,以及对应的详细显示命令 pvdisplay、vgdisplay 和 lvdisplay。
编写 LVM 卷创建脚本
自动化设置 LVM 必须遵循严格的顺序:pvcreate → vgcreate → lvcreate → mkfs → mount。每一步都必须成功后才能执行下一步——请使用 set -euo pipefail,并验证每个命令的输出。
- 调用
pvcreate前,始终检查目标磁盘上没有现有的分区表 - 在非交互式脚本中使用
-y标志,以禁止交互式提示 - 指定
-L(固定大小),或指定-l 100%FREE以使用所有剩余空间 - 执行
mkfs后,使用 LV 的设备路径:/dev/<vgname>/<lvname>
#!/usr/bin/env bash
# Automate LVM setup: PV -> VG -> LV -> mkfs -> mount
set -euo pipefail
DISK='/dev/sdc' # raw disk, no existing partitions
VG_NAME='vg_appdata'
LV_NAME='lv_appdata'
LV_SIZE='10G'
MOUNTPOINT='/mnt/appdata'
FSTYPE='xfs'
echo "[1/6] Initializing Physical Volume on $DISK"
sudo pvcreate -y "$DISK"
echo "[2/6] Creating Volume Group: $VG_NAME"
sudo vgcreate "$VG_NAME" "$DISK"
echo "[3/6] Creating Logical Volume: $LV_NAME (${LV_SIZE})"
sudo lvcreate -y -L "$LV_SIZE" -n "$LV_NAME" "$VG_NAME"
echo "[4/6] Formatting as $FSTYPE"
sudo mkfs."$FSTYPE" "/dev/$VG_NAME/$LV_NAME"
echo "[5/6] Mounting at $MOUNTPOINT"
sudo mkdir -p "$MOUNTPOINT"
sudo mount "/dev/$VG_NAME/$LV_NAME" "$MOUNTPOINT"
echo "[6/6] Done. Disk usage:"
df -h "$MOUNTPOINT"
# Show LVM summary
vgs && lvs在线扩展逻辑卷
LVM 最强大的功能之一是在线调整大小——可以在逻辑卷已挂载且正在使用时,同时扩展逻辑卷及其文件系统。操作流程如下:
- 使用
lvextend扩展 LV(-r标志会在同一步骤中调整文件系统大小) - 如果不使用
-r,请单独调整文件系统大小:ext4 使用resize2fs,xfs 使用xfs_growfs
重要限制:
- xfs 只能扩展,不能缩小——请仔细规划容量
- ext4 可以缩小,但只能在未挂载时进行
- 扩展之前,始终使用
vgdisplay -s验证 VG 中有可用空间
#!/usr/bin/env bash
# Extend an LV and its xfs filesystem online
set -euo pipefail
VG_NAME='vg_appdata'
LV_NAME='lv_appdata'
EXTEND_BY='5G'
LV_DEV="/dev/$VG_NAME/$LV_NAME"
# Confirm VG has enough free space
FREE_GB=$(vgs --noheadings --units g -o vg_free "$VG_NAME" | tr -d ' g')
echo "VG free space: ${FREE_GB}G"
if (( $(echo "$FREE_GB < 5" | bc -l) )); then
echo 'ERROR: Not enough free space in VG' >&2
exit 1
fi
echo "Extending LV by $EXTEND_BY..."
sudo lvextend -L "+${EXTEND_BY}" "$LV_DEV"
echo 'Growing xfs filesystem online...'
sudo xfs_growfs "$LV_DEV"
echo 'New size:'
df -h "$LV_DEV"
lvs "$LV_DEV"创建和格式化文件系统
完成分区或 LVM 设置后,您需要使用文件系统格式化块设备。Linux 管理中常见的选择包括:
- ext4——成熟、支持日志记录,并支持缩小;许多发行版的默认选择(
mkfs.ext4) - xfs——性能高,适合大文件和并行 I/O;RHEL/CentOS 的默认选择(
mkfs.xfs) - btrfs——写时复制,内置快照功能(
mkfs.btrfs) - tmpfs——由 RAM 支持,在 fstab 中指定,无需使用 mkfs
始终设置有意义的文件系统标签(-L 标志),这样设备就可以在 fstab 中通过 LABEL= 引用,作为 UUID 的备用方式。
#!/usr/bin/env bash
# Format a partition and assign a label; print resulting UUID
set -euo pipefail
PARTITION='/dev/sdb1'
FSTYPE='ext4'
LABEL='appdata'
# Safety check: refuse to format a currently mounted device
if findmnt --source "$PARTITION" > /dev/null 2>&1; then
echo "ERROR: $PARTITION is currently mounted. Unmount first." >&2
exit 1
fi
echo "Formatting $PARTITION as $FSTYPE with label '$LABEL'..."
sudo mkfs."$FSTYPE" -L "$LABEL" -F "$PARTITION"
# Retrieve and display the new UUID
NEW_UUID=$(sudo blkid -s UUID -o value "$PARTITION")
echo "Formatted successfully."
echo "Label : $LABEL"
echo "UUID : $NEW_UUID"
echo "Use this in fstab: UUID=$NEW_UUID /mnt/$LABEL $FSTYPE defaults,nofail 0 2"使用 autofs 自动挂载 NFS
对于网络文件系统,使用 fstab 在启动时挂载可能会导致延迟或失败,尤其是在 NFS 服务器暂时无法访问时。autofs 通过按需挂载并在超时后卸载来解决这一问题。
- 主映射文件:
/etc/auto.master——定义挂载点目录及其映射文件 - 直接映射文件:
/etc/auto.nfs——为每个子目录指定选项和 NFS 服务器路径 - 修改后使用
systemctl reload autofs重新加载 - 访问挂载点时,挂载内容会自动出现在配置的目录下
在脚本中,您可以根据 NFS 共享列表动态生成映射文件,然后重新加载 autofs,这对于在多台主机上配置共享存储非常有用。
#!/usr/bin/env bash
# Generate an autofs NFS map file from a share list and reload autofs
set -euo pipefail
NFS_SERVER='192.168.1.50'
AUTO_MAP='/etc/auto.nfs'
AUTO_MASTER='/etc/auto.master'
MOUNT_BASE='/nfs'
# Define shares: localname:remote_path
declare -A SHARES=(
[homes]='/export/homes'
[media]='/export/media'
[backups]='/export/backups'
)
# Write map file
{
echo '# Generated by disk-automation script'
for localname in "${!SHARES[@]}"; do
remote="${SHARES[$localname]}"
echo "$localname -rw,soft,timeo=30 ${NFS_SERVER}:${remote}"
done
} | sudo tee "$AUTO_MAP" > /dev/null
echo "Wrote $AUTO_MAP"
# Ensure master map references this file
if ! grep -qF "$AUTO_MAP" "$AUTO_MASTER"; then
echo "$MOUNT_BASE $AUTO_MAP" | sudo tee -a "$AUTO_MASTER" > /dev/null
echo "Updated $AUTO_MASTER"
fi
sudo systemctl reload autofs && echo 'autofs reloaded'使用 LVM 快照进行安全备份
LVM快照提供逻辑卷在某一时刻的副本,因此可以在不卸载实时文件系统的情况下进行一致性备份。快照使用写时复制技术捕获创建时的状态。
- 创建:
lvcreate -s -n lv_snap -L 2G /dev/vg_data/lv_data - 以只读方式挂载快照进行备份:
mount -o ro /dev/vg_data/lv_snap /mnt/snap - 针对快照挂载点运行
rsync或tar - 备份后删除快照:
umount /mnt/snap && lvremove -f /dev/vg_data/lv_snap
将快照大小保持在源 LV 的 10% 到 20%。如果快照空间用尽,快照就会失效——请使用 lvs -o lv_name,snap_percent 进行监控。
#!/usr/bin/env bash
# Create an LVM snapshot, back up via tar, then remove snapshot
set -euo pipefail
VG='vg_appdata'
ORIGIN_LV='lv_appdata'
SNAP_LV='lv_appdata_snap'
SNAP_SIZE='2G'
SNAP_MOUNT='/mnt/snap_backup'
BACKUP_DEST='/var/backups/appdata'
DATESTAMP=$(date +%Y%m%d_%H%M%S)
trap 'sudo umount "$SNAP_MOUNT" 2>/dev/null; sudo lvremove -f "/dev/$VG/$SNAP_LV" 2>/dev/null' ERR EXIT
echo '[1] Creating snapshot...'
sudo lvcreate -s -n "$SNAP_LV" -L "$SNAP_SIZE" "/dev/$VG/$ORIGIN_LV"
echo '[2] Mounting snapshot read-only...'
sudo mkdir -p "$SNAP_MOUNT"
sudo mount -o ro "/dev/$VG/$SNAP_LV" "$SNAP_MOUNT"
echo '[3] Archiving to backup destination...'
sudo mkdir -p "$BACKUP_DEST"
sudo tar -czf "$BACKUP_DEST/appdata_${DATESTAMP}.tar.gz" -C "$SNAP_MOUNT" .
echo '[4] Cleaning up snapshot...'
sudo umount "$SNAP_MOUNT"
sudo lvremove -f "/dev/$VG/$SNAP_LV"
echo "Backup complete: $BACKUP_DEST/appdata_${DATESTAMP}.tar.gz"知识检查:安全的 fstab 和挂载自动化
测试您对本课所介绍的安全磁盘、文件系统和挂载自动化实践的理解。
课程回顾:磁盘、文件系统和挂载自动化
在本课中,您为 Linux 系统上的安全、可编写脚本的磁盘和存储管理构建了一套完整工具。重点如下:
- 先检查:
lsblk、blkid、df和du会提供进行任何更改前所需的信息。 - 遵循 fstab 规范:始终使用 UUID,始终包含
nofail,编辑前始终备份,并使用findmnt --verify验证。 - 安全挂载:挂载前检查
mountpoint -q,使用logger记录,并使用lsof处理设备忙碌错误。 - LVM 的优势:PV → VG → LV 这一处理流程支持在线扩展和基于快照的备份,无需停机。
- 文件系统选择很重要:xfs 适合高性能场景(只能扩展),ext4 灵活(可在离线时缩小),btrfs 适合原生支持快照的工作负载。
- 按需使用 NFS:autofs 只在访问网络共享时挂载,从而避免启动延迟。
- 快照备份:LVM 快照提供一致的实时备份,但请始终监控
snap_percent,并在备份后及时删除快照。
结合这些模式,您就可以可靠地自动化整个存储生命周期:发现、配置、挂载、调整大小和备份。
常见问题解答
「磁盘、文件系统与挂载自动化」课时是免费的吗?
是的 — 「磁盘、文件系统与挂载自动化」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Linux Command Line & Bash Scripting Mastery 课程的其余内容,请升级到 CoddyKit PRO。 Linux Command Line & Bash Scripting Mastery 课程共包含 4 节课。
「磁盘、文件系统与挂载自动化」这节课中我会学到什么?
检查块设备、管理 fstab 条目,并安全地编写 LVM 和挂载操作脚本。 你通过在浏览器中直接运行的动手代码来练习 Linux Command Line & Bash Scripting Mastery,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Linux Command Line & Bash Scripting Mastery 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Linux Command Line & Bash Scripting Mastery 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「磁盘、文件系统与挂载自动化」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Linux Command Line & Bash Scripting Mastery 课中编写并运行代码吗?
能。每节 Linux Command Line & Bash Scripting Mastery 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 自动化用户与用户组配置
- 控制 systemd 服务并编写单元文件
- 磁盘、文件系统与挂载自动化
- 构建系统健康检查与告警脚本