我帮你修改脚本,将 DISK="/dev/mmcblk0"
和 ROOT_PARTITION="${DISK}p5"
替换为通过 findmnt -no SOURCE /
动态获取根分区设备路径,同时保持其他功能不变。以下是完整的修改后脚本代码:
#!/bin/bash
# 日志文件
LOG_FILE="/var/log/expand_root_and_swapfile.log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "===== 根分区扩展与交换文件创建脚本开始执行: $(date) ====="
# 检查是否以 root 用户运行
if [ "$(id -u)" != "0" ]; then
echo "错误:此脚本需要以 root 权限运行,请使用 sudo 或切换到 root 用户。"
exit 1
fi
# 检查必要工具是否安装(扩展分区和文件系统所需的工具)
if ! command -v parted >/dev/null 2>&1; then
echo "错误:parted 未安装,请先安装 parted(例如:apt install parted)。"
exit 1
fi
if ! command -v resize2fs >/dev/null 2>&1; then
echo "错误:resize2fs 未安装,请先安装 e2fsprogs(例如:apt install e2fsprogs)。"
exit 1
fi
if ! command -v expect >/dev/null 2>&1; then
echo "错误:expect 未安装,请先安装 expect(例如:apt install expect)。"
exit 1
fi
if ! command -v partprobe >/dev/null 2>&1; then
echo "错误:partprobe 未安装,请先安装 parted(例如:apt install parted)。"
exit 1
fi
if ! command -v fsck >/dev/null 2>&1; then
echo "错误:fsck 未安装,请先安装 e2fsprogs(例如:apt install e2fsprogs)。"
exit 1
fi
# 定义交换文件和大小
SWAP_FILE="/swapfile"
SWAP_SIZE_MB=512
# 通过 findmnt 获取根分区设备路径
ROOT_PARTITION=$(findmnt -no SOURCE /)
if [ -z "$ROOT_PARTITION" ]; then
echo "错误:无法通过 findmnt 获取根分区设备路径,请检查系统配置。"
exit 1
fi
# 从根分区路径推导磁盘设备路径(例如 /dev/mmcblk0p5 -> /dev/mmcblk0)
DISK=$(echo "$ROOT_PARTITION" | sed -r 's/p[0-9]+$//')
if [ -z "$DISK" ]; then
echo "错误:无法从根分区路径 $ROOT_PARTITION 推导磁盘设备路径。"
exit 1
fi
# 检查磁盘是否存在
if [ ! -b "$DISK" ]; then
echo "错误:磁盘 $DISK 不存在,请检查设备名称。"
exit 1
fi
# 检查根分区是否存在
if [ ! -b "$ROOT_PARTITION" ]; then
echo "错误:根分区 $ROOT_PARTITION 不存在,请检查分区编号。"
exit 1
fi
# 检查根分区是否挂载
MOUNT_POINT=$(mount | grep "$ROOT_PARTITION" | awk '{print $3}')
if [ -z "$MOUNT_POINT" ]; then
echo "错误:根分区 $ROOT_PARTITION 未挂载,请确保分区已挂载。"
exit 1
fi
echo "根分区 $ROOT_PARTITION 已挂载到 $MOUNT_POINT,可以在线扩展。"
# 显示分区表和可用空间
echo "正在检查磁盘 $DISK 的分区布局..."
parted -s "$DISK" unit MB print free
# 验证根分区是否为最后一个分区且后面有可用空间
FREE_SPACE=$(parted -s "$DISK" unit MB print free | grep -A1 "Number.*Start.*End.*Size" | tail -n 1 | grep "Free Space")
if [ -z "$FREE_SPACE" ]; then
echo "错误:根分区 $ROOT_PARTITION 后面没有可用空间,无法扩展。"
exit 1
fi
# 使用 expect 自动运行 parted,模拟手动步骤:print free -> Fix -> resizepart [分区号] 100% -> quit
PARTITION_NUMBER=$(echo "$ROOT_PARTITION" | grep -o '[0-9]\+$')
if [ -z "$PARTITION_NUMBER" ]; then
echo "错误:无法从根分区路径 $ROOT_PARTITION 提取分区号。"
exit 1
fi
echo "正在运行 parted,自动输入 'Fix' 并调整根分区大小..."
/usr/bin/expect <<EOF
set timeout 30
spawn parted $DISK
expect "(parted)" {
send "print free\r"
expect {
"Fix/Ignore?" {
send "Fix\r"
expect "(parted)" {
send "resizepart $PARTITION_NUMBER 100%\r"
expect "(parted)" {
send "quit\r"
}
}
}
"(parted)" {
send "resizepart $PARTITION_NUMBER 100%\r"
expect "(parted)" {
send "quit\r"
}
}
timeout {
send_user "错误:parted 交互超时\n"
exit 1
}
}
}
expect eof
EOF
if [ $? -ne 0 ]; then
echo "错误:parted 执行失败,请检查日志 $LOG_FILE。"
exit 1
fi
# 通知内核更新分区表
echo "正在通知内核更新分区表..."
partprobe "$DISK" || {
echo "错误:partprobe 失败,尝试使用 blockdev 同步..."
blockdev --rereadpt "$DISK" || {
echo "错误:分区表同步失败,请检查日志 $LOG_FILE。"
exit 1
}
}
# 显示调整后的分区表
echo "根分区调整完成,以下是新的分区布局:"
parted -s "$DISK" unit MB print free
# 检查文件系统一致性(非破坏性检查)
echo "正在检查文件系统一致性(非破坏性)..."
fsck -n "$ROOT_PARTITION" || {
echo "警告:文件系统检查发现问题,建议手动运行 'e2fsck -f $ROOT_PARTITION' 修复(需卸载或重启到单用户模式)。"
echo "继续尝试在线扩展文件系统..."
}
# 执行文件系统扩展
echo "正在扩展根分区文件系统..."
resize2fs "$ROOT_PARTITION" || {
echo "错误:文件系统扩展失败,请检查日志 $LOG_FILE。"
echo "可能需要手动运行 'e2fsck -f $ROOT_PARTITION' 和 'resize2fs $ROOT_PARTITION'。"
exit 1
}
# 显示扩展后的文件系统信息
echo "根分区文件系统扩展完成!以下是新的文件系统信息:"
df -h | grep "$ROOT_PARTITION"
# 检查交换文件相关工具和空间
echo "正在检查交换文件创建所需的工具和空间..."
if ! command -v mkswap >/dev/null 2>&1; then
echo "错误:mkswap 未安装,请先安装 util-linux(例如:apt install util-linux)。"
exit 1
fi
# 检查扩展后根文件系统可用空间是否足够创建 512MB 交换文件
FREE_SPACE_MB=$(df --block-size=1M "$MOUNT_POINT" | tail -n 1 | awk '{print $4}')
if [ -z "$FREE_SPACE_MB" ]; then
echo "错误:无法获取扩展后根文件系统可用空间,请检查 df 命令输出。"
exit 1
fi
if [ "$FREE_SPACE_MB" -lt "$SWAP_SIZE_MB" ]; then
echo "错误:扩展后根文件系统可用空间 ($FREE_SPACE_MB MB) 小于所需的交换文件大小 ($SWAP_SIZE_MB MB)。"
exit 1
fi
echo "扩展后根文件系统可用空间为 $FREE_SPACE_MB MB,足以创建 $SWAP_SIZE_MB MB 交换文件。"
# 创建交换文件
echo "正在创建 $SWAP_SIZE_MB MB 交换文件 ($SWAP_FILE)..."
if [ -f "$SWAP_FILE" ]; then
echo "交换文件 $SWAP_FILE 已存在,跳过创建。"
else
dd if=/dev/zero of="$SWAP_FILE" bs=1M count="$SWAP_SIZE_MB" status=progress || {
echo "错误:创建交换文件失败,请检查日志 $LOG_FILE。"
exit 1
}
chmod 600 "$SWAP_FILE" || {
echo "错误:设置交换文件权限失败,请检查日志 $LOG_FILE。"
exit 1
}
mkswap "$SWAP_FILE" || {
echo "错误:格式化交换文件失败,请检查日志 $LOG_FILE。"
exit 1
}
fi
# 启用交换文件
echo "正在启用交换文件..."
swapon "$SWAP_FILE" || {
echo "错误:启用交换文件失败,请检查日志 $LOG_FILE。"
exit 1
}
# 添加交换文件到 fstab
echo "正在将交换文件添加到 /etc/fstab..."
if ! grep -q "$SWAP_FILE" /etc/fstab; then
echo "$SWAP_FILE none swap sw 0 0" >> /etc/fstab
echo "交换文件已添加到 /etc/fstab。"
else
echo "交换文件已在 /etc/fstab 中,无需重复添加。"
fi
# 显示交换空间状态
echo "交换文件创建并启用完成!以下是交换空间信息:"
swapon --show
# 禁用脚本以防止下次启动重复执行
systemctl disable auto-expand-root.service
echo "脚本已完成并禁用自动执行,避免重复运行。"
echo "===== 根分区扩展与交换文件创建脚本执行完成: $(date) ====="
修改说明
动态获取根分区:
- 使用
ROOT_PARTITION=$(findmnt -no SOURCE /)
获取根分区的设备路径(如/dev/mmcblk0p5
)。 - 添加了错误检查,确保
findmnt
能正确返回根分区路径。
- 使用
推导磁盘设备路径:
- 从根分区路径(如
/dev/mmcblk0p5
)通过sed -r 's/p[0-9]+$//'
提取磁盘设备路径(如/dev/mmcblk0
)。 - 添加了错误检查,确保能正确提取磁盘路径。
- 从根分区路径(如
动态获取分区号:
- 在
parted
的resizepart
命令中,使用PARTITION_NUMBER=$(echo "$ROOT_PARTITION" | grep -o '[0-9]\+$')
提取分区号(如5
),以动态调整根分区。 - 添加了错误检查,确保能正确提取分区号。
- 在
其他部分保持不变:
- 保留了原脚本的所有功能,包括日志记录、分区扩展、文件系统扩展、交换文件创建等。
- 错误提示和日志输出中的设备路径已更新为动态获取的
$ROOT_PARTITION
和$DISK
。
注意事项
- 脚本假设根分区是最后一个分区且后面有可用空间。如果实际情况不同,可能需要进一步调整逻辑。
- 确保
findmnt
命令可用(通常包含在util-linux
包中)。 - 如果根分区路径格式非标准(如不是
/dev/mmcblk0pX
形式),sed
提取磁盘路径的逻辑可能需要调整。
原脚本:
#!/bin/bash
# 日志文件
LOG_FILE="/var/log/expand_root_and_swapfile.log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "===== 根分区扩展与交换文件创建脚本开始执行: $(date) ====="
# 检查是否以 root 用户运行
if [ "$(id -u)" != "0" ]; then
echo "错误:此脚本需要以 root 权限运行,请使用 sudo 或切换到 root 用户。"
exit 1
fi
# 检查必要工具是否安装(扩展分区和文件系统所需的工具)
if ! command -v parted >/dev/null 2>&1; then
echo "错误:parted 未安装,请先安装 parted(例如:apt install parted)。"
exit 1
fi
if ! command -v resize2fs >/dev/null 2>&1; then
echo "错误:resize2fs 未安装,请先安装 e2fsprogs(例如:apt install e2fsprogs)。"
exit 1
fi
if ! command -v expect >/dev/null 2>&1; then
echo "错误:expect 未安装,请先安装 expect(例如:apt install expect)。"
exit 1
fi
if ! command -v partprobe >/dev/null 2>&1; then
echo "错误:partprobe 未安装,请先安装 parted(例如:apt install parted)。"
exit 1
fi
if ! command -v fsck >/dev/null 2>&1; then
echo "错误:fsck 未安装,请先安装 e2fsprogs(例如:apt install e2fsprogs)。"
exit 1
fi
# 定义目标磁盘、分区和交换文件
DISK="/dev/mmcblk0"
ROOT_PARTITION="${DISK}p5"
SWAP_FILE="/swapfile"
SWAP_SIZE_MB=512
# 检查磁盘是否存在
if [ ! -b "$DISK" ]; then
echo "错误:磁盘 $DISK 不存在,请检查设备名称。"
exit 1
fi
# 检查根分区是否存在
if [ ! -b "$ROOT_PARTITION" ]; then
echo "错误:根分区 $ROOT_PARTITION 不存在,请检查分区编号。"
exit 1
fi
# 检查根分区是否挂载
MOUNT_POINT=$(mount | grep "$ROOT_PARTITION" | awk '{print $3}')
if [ -z "$MOUNT_POINT" ]; then
echo "错误:根分区 $ROOT_PARTITION 未挂载,请确保分区已挂载。"
exit 1
fi
echo "根分区 $ROOT_PARTITION 已挂载到 $MOUNT_POINT,可以在线扩展。"
# 显示分区表和可用空间
echo "正在检查磁盘 $DISK 的分区布局..."
parted -s "$DISK" unit MB print free
# 验证根分区是否为最后一个分区且后面有可用空间
FREE_SPACE=$(parted -s "$DISK" unit MB print free | grep -A1 "Number.*Start.*End.*Size" | tail -n 1 | grep "Free Space")
if [ -z "$FREE_SPACE" ]; then
echo "错误:根分区 $ROOT_PARTITION 后面没有可用空间,无法扩展。"
exit 1
fi
# 使用 expect 自动运行 parted,模拟手动步骤:print free -> Fix -> resizepart 5 100% -> quit
echo "正在运行 parted,自动输入 'Fix' 并调整根分区大小..."
/usr/bin/expect <<EOF
set timeout 30
spawn parted $DISK
expect "(parted)" {
send "print free\r"
expect {
"Fix/Ignore?" {
send "Fix\r"
expect "(parted)" {
send "resizepart 5 100%\r"
expect "(parted)" {
send "quit\r"
}
}
}
"(parted)" {
send "resizepart 5 100%\r"
expect "(parted)" {
send "quit\r"
}
}
timeout {
send_user "错误:parted 交互超时\n"
exit 1
}
}
}
expect eof
EOF
if [ $? -ne 0 ]; then
echo "错误:parted 执行失败,请检查日志 $LOG_FILE。"
exit 1
fi
# 通知内核更新分区表
echo "正在通知内核更新分区表..."
partprobe "$DISK" || {
echo "错误:partprobe 失败,尝试使用 blockdev 同步..."
blockdev --rereadpt "$DISK" || {
echo "错误:分区表同步失败,请检查日志 $LOG_FILE。"
exit 1
}
}
# 显示调整后的分区表
echo "根分区调整完成,以下是新的分区布局:"
parted -s "$DISK" unit MB print free
# 检查文件系统一致性(非破坏性检查)
echo "正在检查文件系统一致性(非破坏性)..."
fsck -n "$ROOT_PARTITION" || {
echo "警告:文件系统检查发现问题,建议手动运行 'e2fsck -f /dev/mmcblk0p5' 修复(需卸载或重启到单用户模式)。"
echo "继续尝试在线扩展文件系统..."
}
# 执行文件系统扩展
echo "正在扩展根分区文件系统..."
resize2fs "$ROOT_PARTITION" || {
echo "错误:文件系统扩展失败,请检查日志 $LOG_FILE。"
echo "可能需要手动运行 'e2fsck -f /dev/mmcblk0p5' 和 'resize2fs /dev/mmcblk0p5'。"
exit 1
}
# 显示扩展后的文件系统信息
echo "根分区文件系统扩展完成!以下是新的文件系统信息:"
df -h | grep "$ROOT_PARTITION"
# 检查交换文件相关工具和空间
echo "正在检查交换文件创建所需的工具和空间..."
if ! command -v mkswap >/dev/null 2>&1; then
echo "错误:mkswap 未安装,请先安装 util-linux(例如:apt install util-linux)。"
exit 1
fi
# 检查扩展后根文件系统可用空间是否足够创建 512MB 交换文件
FREE_SPACE_MB=$(df --block-size=1M "$MOUNT_POINT" | tail -n 1 | awk '{print $4}')
if [ -z "$FREE_SPACE_MB" ]; then
echo "错误:无法获取扩展后根文件系统可用空间,请检查 df 命令输出。"
exit 1
fi
if [ "$FREE_SPACE_MB" -lt "$SWAP_SIZE_MB" ]; then
echo "错误:扩展后根文件系统可用空间 ($FREE_SPACE_MB MB) 小于所需的交换文件大小 ($SWAP_SIZE_MB MB)。"
exit 1
fi
echo "扩展后根文件系统可用空间为 $FREE_SPACE_MB MB,足以创建 $SWAP_SIZE_MB MB 交换文件。"
# 创建交换文件
echo "正在创建 $SWAP_SIZE_MB MB 交换文件 ($SWAP_FILE)..."
if [ -f "$SWAP_FILE" ]; then
echo "交换文件 $SWAP_FILE 已存在,跳过创建。"
else
dd if=/dev/zero of="$SWAP_FILE" bs=1M count="$SWAP_SIZE_MB" status=progress || {
echo "错误:创建交换文件失败,请检查日志 $LOG_FILE。"
exit 1
}
chmod 600 "$SWAP_FILE" || {
echo "错误:设置交换文件权限失败,请检查日志 $LOG_FILE。"
exit 1
}
mkswap "$SWAP_FILE" || {
echo "错误:格式化交换文件失败,请检查日志 $LOG_FILE。"
exit 1
}
fi
# 启用交换文件
echo "正在启用交换文件..."
swapon "$SWAP_FILE" || {
echo "错误:启用交换文件失败,请检查日志 $LOG_FILE。"
exit 1
}
# 添加交换文件到 fstab
echo "正在将交换文件添加到 /etc/fstab..."
if ! grep -q "$SWAP_FILE" /etc/fstab; then
echo "$SWAP_FILE none swap sw 0 0" >> /etc/fstab
echo "交换文件已添加到 /etc/fstab。"
else
echo "交换文件已在 /etc/fstab 中,无需重复添加。"
fi
# 显示交换空间状态
echo "交换文件创建并启用完成!以下是交换空间信息:"
swapon --show
# 禁用脚本以防止下次启动重复执行
systemctl disable auto-expand-root.service
echo "脚本已完成并禁用自动执行,避免重复运行。"
echo "===== 根分区扩展与交换文件创建脚本执行完成: $(date) ====="
其中DISK="/dev/mmcblk0"
ROOT_PARTITION="${DISK}p5"是固定的,能不能改成通过findmnt -no SOURCE /来获取,其它功能不变,输出完整脚本代码,中文回答
评论 (0)