qemu-img 使用手册
- [1. 命令概述](#1. 命令概述)
- [2. 镜像格式支持](#2. 镜像格式支持)
- [3. 主要命令详解](#3. 主要命令详解)
-
- [3.1 create - 创建镜像](#3.1 create - 创建镜像)
- [案例 1:创建基本镜像](#案例 1:创建基本镜像)
- [案例 2:创建增量镜像(链式镜像)](#案例 2:创建增量镜像(链式镜像))
- [案例 3:创建带有加密的镜像](#案例 3:创建带有加密的镜像)
- [3.2 convert - 转换镜像格式](#3.2 convert - 转换镜像格式)
- [案例 4:格式转换](#案例 4:格式转换)
- [案例 5:跨虚拟化平台迁移](#案例 5:跨虚拟化平台迁移)
- [案例 6:批量转换脚本](#案例 6:批量转换脚本)
- [3.3 resize - 调整镜像大小](#3.3 resize - 调整镜像大小)
- [案例 7:扩展镜像容量](#案例 7:扩展镜像容量)
- [案例 8:在线扩容工作流](#案例 8:在线扩容工作流)
- [3.4 info - 查看镜像信息](#3.4 info - 查看镜像信息)
- [案例 9:检查镜像信息](#案例 9:检查镜像信息)
- [3.5 snapshot - 快照管理](#3.5 snapshot - 快照管理)
- [案例 10:快照管理实战](#案例 10:快照管理实战)
- [3.6 check - 检查镜像完整性](#3.6 check - 检查镜像完整性)
- [案例 11:镜像完整性检查](#案例 11:镜像完整性检查)
- [3.7 compare - 比较镜像差异](#3.7 compare - 比较镜像差异)
- [案例 12:镜像比较](#案例 12:镜像比较)
- [3.8 map - 显示镜像映射](#3.8 map - 显示镜像映射)
- [案例 13:查看镜像分配情况](#案例 13:查看镜像分配情况)
- [3.9 amend - 修改镜像选项](#3.9 amend - 修改镜像选项)
- [案例 14:修改镜像属性](#案例 14:修改镜像属性)
- [3.10 benchmark - 性能测试](#3.10 benchmark - 性能测试)
- [案例 15:磁盘性能基准测试](#案例 15:磁盘性能基准测试)
- [4. 实际应用案例](#4. 实际应用案例)
-
- [案例 16:完整虚拟机迁移流程](#案例 16:完整虚拟机迁移流程)
- [案例 17:自动化备份系统](#案例 17:自动化备份系统)
- [案例 18:镜像优化脚本](#案例 18:镜像优化脚本)
- [案例 19:磁盘镜像恢复工具](#案例 19:磁盘镜像恢复工具)
- [案例 20:创建云镜像模板](#案例 20:创建云镜像模板)
- [5. 故障排除和最佳实践](#5. 故障排除和最佳实践)
1. 命令概述
qemu-img 是 QEMU 的磁盘镜像管理工具,支持创建、转换、修改、检查和管理虚拟磁盘镜像。
bash
基本语法:qemu-img [command] [options]
2. 镜像格式支持
| 格式 | 描述 | 特点 |
|---|---|---|
| raw | 原始格式 | 简单,直接访问文件,性能好 |
| qcow2 | QEMU 镜像格式 | 支持压缩、加密、快照、稀疏文件 |
| qcow | 旧版 QEMU 格式 | 已弃用,向后兼容 |
| vdi | VirtualBox 格式 | VirtualBox 兼容 |
| vmdk | VMware 格式 | VMware 兼容 |
| vhd/vpc | VirtualPC 格式 | Hyper-V 兼容 |
| vhdx | Hyper-V 格式 | Hyper-V 新一代格式 |
| parallels | Parallels Desktop | Parallels 兼容 |
| bochs | Bochs 格式 | 模拟器兼容 |
| cloop | 压缩 loop 设备 | 只读压缩格式 |
| dmg | Apple Disk Image | macOS 兼容 |
3. 主要命令详解
3.1 create - 创建镜像
bash
语法:qemu-img create [-f fmt] [-b backing_file] filename [size]
选项:
-f fmt:指定镜像格式-b backing_file:创建增量镜像(基于基础镜像)-F backing_fmt:指定基础镜像格式-o options:指定格式特定选项
案例 1:创建基本镜像
bash
# 创建 20GB 的 raw 格式镜像
qemu-img create -f raw disk.raw 20G
# 创建 50GB 的 qcow2 格式镜像
qemu-img create -f qcow2 ubuntu.qcow2 50G
# 创建带预分配的 qcow2 镜像(更快)
qemu-img create -f qcow2 -o preallocation=full vmdisk.qcow2 100G
# 创建稀疏镜像(qcow2 默认)
qemu-img create -f qcow2 sparse.qcow2 1T
ls -lh sparse.qcow2 # 显示实际占用很小
案例 2:创建增量镜像(链式镜像)
bash
# 1. 创建基础镜像
qemu-img create -f qcow2 base.qcow2 50G
# 2. 从基础镜像启动并安装操作系统
qemu-system-x86_64 -hda base.qcow2 -cdrom ubuntu.iso
# 3. 基于基础镜像创建增量镜像(节省空间)
qemu-img create -f qcow2 -b base.qcow2 -F qcow2 snapshot1.qcow2
# 4. 启动增量镜像(更改不会影响基础镜像)
qemu-system-x86_64 -hda snapshot1.qcow2
案例 3:创建带有加密的镜像
bash
# 创建加密的 qcow2 镜像
qemu-img create -f qcow2 \
-o encryption,encrypt.key-secret=sec0 \
encrypted.qcow2 10G
# 需要配合 QEMU 使用密钥
echo "mysecretpassword" > secret.txt
3.2 convert - 转换镜像格式
bash
语法:qemu-img convert [-c] [-f fmt] [-O output_fmt] [-o options] input output
选项:
-c:压缩目标镜像-p:显示进度-f fmt:输入镜像格式(可自动检测)-O output_fmt:输出镜像格式-o options:输出选项-s snapshot_id:从快照转换
案例 4:格式转换
bash
# 将 raw 转换为 qcow2
qemu-img convert -f raw -O qcow2 disk.raw disk.qcow2
# 将 vmdk 转换为 qcow2(显示进度)
qemu-img convert -p -f vmdk -O qcow2 vmware.vmdk qemu.qcow2
# 压缩转换(适用于 qcow2)
qemu-img convert -c -p -f raw -O qcow2 large.raw compressed.qcow2
# 转换并指定集群大小
qemu-img convert -f raw -O qcow2 \
-o cluster_size=2M \
input.raw output.qcow2
案例 5:跨虚拟化平台迁移
bash
# 从 VMware 迁移到 QEMU
qemu-img convert -p \
-f vmdk \
-O qcow2 \
-o compat=1.1 \
vmware-disk.vmdk \
kvm-disk.qcow2
# 从 VirtualBox 迁移到 QEMU
qemu-img convert -p \
-f vdi \
-O qcow2 \
vbox-disk.vdi \
qemu-disk.qcow2
# 从 Hyper-V 迁移到 QEMU
qemu-img convert -p \
-f vhdx \
-O qcow2 \
hyperv-disk.vhdx \
qemu-disk.qcow2
案例 6:批量转换脚本
bash
#!/bin/bash
# convert-all.sh
for img in *.vmdk *.vdi *.vhd *.vhdx; do
if [ -f "$img" ]; then
output="${img%.*}.qcow2"
echo "Converting $img to $output..."
qemu-img convert -p -f raw -O qcow2 "$img" "$output"
fi
done
3.3 resize - 调整镜像大小
bash
语法:qemu-img resize filename [+|-]size
注意:
- 只增加:可以直接调整
- 减少大小:需要先收缩文件系统
- raw 格式可以直接调整
- qcow2 需要在虚拟机内调整文件系统
案例 7:扩展镜像容量
bash
# 增加 10GB
qemu-img resize vmdisk.qcow2 +10G
# 设置绝对大小到 100GB
qemu-img resize vmdisk.qcow2 100G
# 缩小镜像(危险!需要先在虚拟机内缩小文件系统)
# 1. 在虚拟机内缩小文件系统
# 2. 缩小镜像
qemu-img resize vmdisk.qcow2 80G
案例 8:在线扩容工作流
bash
#!/bin/bash
# resize-vm.sh - 安全调整虚拟机磁盘大小
IMAGE="ubuntu.qcow2"
NEW_SIZE="100G"
# 1. 检查镜像信息
echo "当前镜像信息:"
qemu-img info "$IMAGE"
# 2. 调整镜像大小
echo "调整镜像大小为 $NEW_SIZE..."
qemu-img resize "$IMAGE" "$NEW_SIZE"
# 3. 启动虚拟机调整分区
echo "请启动虚拟机并调整分区:"
echo "1. sudo fdisk /dev/sda"
echo "2. 删除分区并重新创建"
echo "3. sudo resize2fs /dev/sda1"
# 4. 验证调整结果
echo -e "\n调整后的镜像信息:"
qemu-img info "$IMAGE"
3.4 info - 查看镜像信息
bash
语法:qemu-img info filename
案例 9:检查镜像信息
bash
# 查看镜像详细信息
qemu-img info ubuntu.qcow2
# 输出示例:
# image: ubuntu.qcow2
# file format: qcow2
# virtual size: 50 GiB (53687091200 bytes)
# disk size: 12 GiB
# cluster_size: 65536
# Format specific information:
# compat: 1.1
# compression type: zlib
# lazy refcounts: true
# refcount bits: 16
# corrupt: false
# extended l2: false
# 查看加密信息
qemu-img info --force-share encrypted.qcow2
# 查看快照信息
qemu-img info --output=json vmdisk.qcow2 | jq '.snapshots'
3.5 snapshot - 快照管理
bash
语法:
qemu-img snapshot -l filename # 列出快照
qemu-img snapshot -c snapshot_name filename # 创建快照
qemu-img snapshot -a snapshot_name filename # 应用快照
qemu-img snapshot -d snapshot_name filename # 删除快照
案例 10:快照管理实战
bash
# 1. 创建测试镜像
qemu-img create -f qcow2 test.qcow2 10G
# 2. 创建多个快照
qemu-img snapshot -c "clean-install" test.qcow2
qemu-img snapshot -c "after-updates" test.qcow2
qemu-img snapshot -c "before-software" test.qcow2
# 3. 列出快照
qemu-img snapshot -l test.qcow2
# 输出:
# Snapshot list:
# ID TAG VM SIZE DATE VM CLOCK
# 1 clean-install 0 2024-01-15 10:00:00 00:00:00.000
# 2 after-updates 0 2024-01-15 11:00:00 00:00:00.000
# 3 before-software 0 2024-01-15 12:00:00 00:00:00.000
# 4. 恢复到特定快照
qemu-img snapshot -a "clean-install" test.qcow2
# 5. 删除不再需要的快照
qemu-img snapshot -d "before-software" test.qcow2
# 6. 批量删除快照脚本
for snap in $(qemu-img snapshot -l test.qcow2 | grep -o 'snapshot-.*' | head -n -3); do
qemu-img snapshot -d "$snap" test.qcow2
done
3.6 check - 检查镜像完整性
bash
语法:qemu-img check [-f fmt] filename
案例 11:镜像完整性检查
bash
# 基本检查
qemu-img check ubuntu.qcow2
# 详细检查
qemu-img check -r all corrupted.qcow2
# -r leak: 修复泄漏的集群
# -r all: 尝试修复所有问题
# 检查并输出修复信息
qemu-img check -r leaks damaged.qcow2 2>&1 | tee repair.log
# 批量检查脚本
for img in *.qcow2; do
echo "检查 $img..."
qemu-img check "$img"
if [ $? -ne 0 ]; then
echo "警告: $img 可能损坏"
fi
done
3.7 compare - 比较镜像差异
bash
语法:qemu-img compare [-f fmt] [-F fmt] [-p] [-q] [-s] filename1 filename2
案例 12:镜像比较
bash
# 比较两个镜像
qemu-img compare base.qcow2 modified.qcow2
# 静默模式(只返回退出码)
qemu-img compare -q image1.qcow2 image2.qcow2
if [ $? -eq 0 ]; then
echo "镜像相同"
else
echo "镜像不同"
fi
# 显示进度
qemu-img compare -p base.qcow2 snapshot.qcow2
# 比较不同格式的镜像
qemu-img compare -f raw -F qcow2 disk.raw disk.qcow2
3.8 map - 显示镜像映射
bash
语法:qemu-img map [-f fmt] [--output=fmt] filename
案例 13:查看镜像分配情况
bash
# 显示镜像文件分配映射
qemu-img map --output=json ubuntu.qcow2
# 查看稀疏文件的实际分配
qemu-img map sparse.qcow2 | head -20
# 计算实际使用空间
qemu-img map vmdisk.qcow2 | awk '{sum += $3} END {print "已分配空间: " sum/1024/1024 " MB"}'
3.9 amend - 修改镜像选项
bash
语法:qemu-img amend [-f fmt] [-t cache] -o options filename
案例 14:修改镜像属性
bash
# 修改兼容性版本
qemu-img amend -f qcow2 -o compat=1.1 old.qcow2
# 添加加密
qemu-img amend -f qcow2 \
-o encrypt.format=luks,encrypt.key-secret=sec0 \
disk.qcow2
# 修改压缩设置
qemu-img amend -f qcow2 -o compression_type=zstd image.qcow2
# 修改集群大小
qemu-img amend -f qcow2 -o cluster_size=2M large.qcow2
3.10 benchmark - 性能测试
bash
语法:qemu-img bench [-f fmt] [-c count] [-d depth] [-n] [-s buffer_size] [-S step_size] [-t cache] [-w] filename
案例 15:磁盘性能基准测试
bash
# 顺序读取测试
qemu-img bench -f qcow2 -n -w ubuntu.qcow2
# 指定测试参数
qemu-img bench -f qcow2 \
-c 1000 \
-d 32 \
-s 4k \
-t none \
test.qcow2
# 比较不同缓存策略
echo "=== writeback 缓存 ==="
qemu-img bench -f qcow2 -t writeback -w perf.qcow2
echo "=== writethrough 缓存 ==="
qemu-img bench -f qcow2 -t writethrough -w perf.qcow2
echo "=== none 缓存 ==="
qemu-img bench -f qcow2 -t none -w perf.qcow2
4. 实际应用案例
案例 16:完整虚拟机迁移流程
bash
#!/bin/bash
# migrate-vm.sh - 迁移虚拟机到新主机
SOURCE_VM="source-vm"
DEST_HOST="user@newhost"
BACKUP_DIR="/backup/vms"
# 1. 在源主机停止虚拟机
virsh shutdown "$SOURCE_VM"
sleep 30
# 2. 导出镜像信息
virsh dumpxml "$SOURCE_VM" > "$SOURCE_VM.xml"
# 3. 转换和压缩镜像
echo "转换镜像格式..."
qemu-img convert -p \
-O qcow2 \
-c \
/var/lib/libvirt/images/"$SOURCE_VM".img \
"$BACKUP_DIR"/"$SOURCE_VM".qcow2
# 4. 传输到目标主机
echo "传输文件..."
scp "$BACKUP_DIR"/"$SOURCE_VM".qcow2 "$DEST_HOST":/var/lib/libvirt/images/
scp "$SOURCE_VM".xml "$DEST_HOST":/tmp/
# 5. 在目标主机导入
ssh "$DEST_HOST" "
virsh define /tmp/$SOURCE_VM.xml
virsh start $SOURCE_VM
"
echo "迁移完成!"
案例 17:自动化备份系统
bash
#!/bin/bash
# backup-vm.sh - 自动备份虚拟机
VM_LIST=("webserver" "database" "fileserver")
BACKUP_ROOT="/backup/vms"
RETENTION_DAYS=7
# 创建备份目录
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_ROOT/$DATE"
mkdir -p "$BACKUP_DIR"
# 备份每个虚拟机
for VM in "${VM_LIST[@]}"; do
echo "备份虚拟机: $VM"
# 1. 创建外部快照
virsh snapshot-create-as \
--domain "$VM" \
--name "backup-$DATE" \
--disk-only \
--atomic
# 2. 备份镜像
SRC_IMG="/var/lib/libvirt/images/${VM}.qcow2"
BACKUP_IMG="$BACKUP_DIR/${VM}_${DATE}.qcow2"
qemu-img convert -p \
-O qcow2 \
"$SRC_IMG" \
"$BACKUP_IMG"
# 3. 清理快照
virsh blockcommit "$VM" vda --active --pivot
# 4. 删除快照文件
virsh snapshot-delete \
--domain "$VM" \
--metadata "backup-$DATE"
echo "完成备份: $BACKUP_IMG"
done
# 清理旧备份
find "$BACKUP_ROOT" -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;
案例 18:镜像优化脚本
bash
#!/bin/bash
# optimize-images.sh - 优化所有 qcow2 镜像
IMAGE_DIR="/var/lib/libvirt/images"
LOG_FILE="/var/log/qemu-img-optimize.log"
echo "开始优化镜像 $(date)" | tee -a "$LOG_FILE"
for IMG in "$IMAGE_DIR"/*.qcow2; do
if [ -f "$IMG" ]; then
echo "处理: $IMG" | tee -a "$LOG_FILE"
# 1. 检查镜像
qemu-img check "$IMG" 2>&1 | tee -a "$LOG_FILE"
# 2. 转换为新格式(去碎片)
TEMP_IMG="${IMG}.optimized"
qemu-img convert -p \
-O qcow2 \
-o cluster_size=2M,preallocation=metadata \
"$IMG" "$TEMP_IMG" 2>&1 | tee -a "$LOG_FILE"
# 3. 替换原镜像
ORIG_SIZE=$(stat -c%s "$IMG")
NEW_SIZE=$(stat -c%s "$TEMP_IMG")
echo "原始大小: $ORIG_SIZE, 优化后: $NEW_SIZE" | tee -a "$LOG_FILE"
if [ $NEW_SIZE -lt $ORIG_SIZE ]; then
mv "$TEMP_IMG" "$IMG"
echo "优化完成,节省空间: $(( (ORIG_SIZE - NEW_SIZE) / 1024 / 1024 )) MB" | tee -a "$LOG_FILE"
else
rm "$TEMP_IMG"
echo "优化未节省空间,保持原样" | tee -a "$LOG_FILE"
fi
echo "---" | tee -a "$LOG_FILE"
fi
done
echo "优化完成 $(date)" | tee -a "$LOG_FILE"
案例 19:磁盘镜像恢复工具
bash
#!/bin/bash
# recover-disk.sh - 从损坏的镜像中恢复数据
CORRUPTED_IMG="$1"
RECOVERY_DIR="recovered_$(date +%Y%m%d_%H%M%S)"
if [ ! -f "$CORRUPTED_IMG" ]; then
echo "用法: $0 <损坏的镜像文件>"
exit 1
fi
mkdir -p "$RECOVERY_DIR"
echo "尝试恢复镜像: $CORRUPTED_IMG"
echo "输出目录: $RECOVERY_DIR"
# 1. 尝试修复
echo "步骤1: 尝试修复镜像..."
qemu-img check -r all "$CORRUPTED_IMG" 2>&1 | tee "$RECOVERY_DIR/repair.log"
# 2. 转换为 raw 格式(更易恢复)
echo "步骤2: 转换为 raw 格式..."
qemu-img convert -f qcow2 -O raw "$CORRUPTED_IMG" "$RECOVERY_DIR/disk.raw" 2>&1 | tee -a "$RECOVERY_DIR/convert.log"
# 3. 尝试挂载
echo "步骤3: 尝试挂载分区..."
sudo losetup -fP "$RECOVERY_DIR/disk.raw"
LOOP_DEV=$(losetup -l | grep disk.raw | awk '{print $1}')
# 尝试扫描分区
sudo fdisk -l "$LOOP_DEV" > "$RECOVERY_DIR/partition-info.txt"
# 4. 尝试恢复文件
echo "步骤4: 尝试恢复文件..."
for PART in ${LOOP_DEV}p*; do
if [ -b "$PART" ]; then
PART_NUM=${PART#*p}
echo "处理分区 $PART_NUM..."
# 尝试使用 photorec
sudo photorec /log /d "$RECOVERY_DIR/part${PART_NUM}_recovered" "$PART" 2>&1 | tee "$RECOVERY_DIR/part${PART_NUM}_photorec.log"
# 尝试使用 testdisk
sudo testdisk /log /d "$RECOVERY_DIR" "$PART" 2>&1 | tee "$RECOVERY_DIR/part${PART_NUM}_testdisk.log"
fi
done
# 5. 清理
sudo losetup -d "$LOOP_DEV"
echo "恢复完成!结果保存在: $RECOVERY_DIR"
案例 20:创建云镜像模板
bash
#!/bin/bash
# create-cloud-image.sh - 创建云就绪镜像
BASE_IMAGE="ubuntu-22.04-server-cloudimg-amd64.img"
OUTPUT_IMAGE="custom-cloud.qcow2"
IMAGE_SIZE="10G"
# 1. 下载基础云镜像
if [ ! -f "$BASE_IMAGE" ]; then
wget https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-amd64.img
fi
# 2. 创建自定义镜像
qemu-img create -f qcow2 -b "$BASE_IMAGE" -F qcow2 "$OUTPUT_IMAGE" "$IMAGE_SIZE"
# 3. 修改镜像(使用 virt-customize)
if command -v virt-customize &> /dev/null; then
virt-customize -a "$OUTPUT_IMAGE" \
--update \
--install qemu-guest-agent,cloud-init \
--run-command "useradd -m admin" \
--ssh-inject admin:file:/home/$(whoami)/.ssh/id_rsa.pub \
--hostname "cloud-instance" \
--timezone "Asia/Shanghai" \
--firstboot-command "dpkg-reconfigure openssh-server"
fi
# 4. 压缩和优化
echo "优化镜像..."
qemu-img convert -p -O qcow2 -c "$OUTPUT_IMAGE" "compressed-$OUTPUT_IMAGE"
# 5. 生成校验和
md5sum "compressed-$OUTPUT_IMAGE" > "compressed-$OUTPUT_IMAGE.md5"
echo "云镜像创建完成: compressed-$OUTPUT_IMAGE"
5. 故障排除和最佳实践
常见问题解决:
-
镜像损坏
bash# 尝试修复 qemu-img check -r all damaged.qcow2 # 重新构建 qemu-img convert -f qcow2 -O qcow2 damaged.qcow2 repaired.qcow2 -
空间不足
bash# 检查实际使用 qemu-img info disk.qcow2 # 清理空间 qemu-img convert -O qcow2 disk.qcow2 compact.qcow2 -
性能问题
bash# 检查碎片 qemu-img map disk.qcow2 | wc -l # 重新整理 qemu-img convert -O qcow2 disk.qcow2 defrag.qcow2
最佳实践:
-
定期维护
bash# 每月执行一次镜像优化 qemu-img convert -O qcow2 production.qcow2 production-optimized.qcow2 -
监控镜像健康
bash# 每日检查脚本 for img in /vms/*.qcow2; do qemu-img check "$img" || echo "警告: $img 需要检查" done -
备份策略
bash# 增量备份 qemu-img create -f qcow2 -b base.qcow2 incremental-$(date +%Y%m%d).qcow2
性能调优参数:
bash
# 高性能生产环境配置
qemu-img convert -O qcow2 \
-o cluster_size=2M,preallocation=metadata,lazy_refcounts=on \
input.raw output.qcow2
# 开发测试环境(节省空间)
qemu-img create -f qcow2 \
-o cluster_size=64K,compression_type=zstd \
test.qcow2 20G