从整个磁盘(设备)的映像中挂载单个分区。

我用XX软件制作了整个硬盘的镜像。
dd if=/dev/sda of=/media/external_media/sda.img

现在的问题是,我想挂载那个磁盘上的一个ext4文件系统,但是...
mount -t ext4 -o loop /media/external_media/sda.img /media/sda_image

显然,由于镜像包含整个磁盘(MBR、其他分区),而不仅仅是我需要的分区,所以会出现超级块错误。所以我想我应该找到一种方法让磁盘镜像显示在/dev/文件夹中...
有人知道怎么做吗?
附注:我总是可以将镜像重新写入原始磁盘,但那样很不方便(我已经更新了操作系统,希望保持原样)。

你可以考虑这个链接:https://technewskb.com/mount-dd-image-linux-using-terminal-commands/ 或者这个链接:https://lettoknow.com/techniques-mount-dd-image-file/ - Cadoiz
10个回答

获取图像的分区布局
$ sudo fdisk -lu sda.img
...
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
...
  Device Boot      Start         End      Blocks   Id  System
sda.img1   *          56     6400000     3199972+   c  W95 FAT32 (LBA)

计算图像开始到分区开始的偏移量
扇区大小 * 开始位置 = (在此情况下) 512 * 56 = 28672
使用偏移量将其挂载到/dev/loop0上
sudo losetup -o 28672 /dev/loop0 sda.img

现在分区位于/dev/loop0上。您可以对其进行fsck、挂载等操作。
sudo fsck -fv /dev/loop0
sudo mount /dev/loop0 /mnt

卸载

sudo umount /mnt
sudo losetup -d /dev/loop0

非常感谢!效果很好!你让我开心了(还救了一只无辜的豹猫免于被残忍删除;P) - Nicola Feltrin
16至少在bash中,shell甚至可以为您进行数学计算:sudo losetup -o $((56*512)) /dev/loop0 sda.img - Enno Gröper
3这不仅仅是有帮助,而且绝对棒极了。 - andho
如果存在 .img1 和 .img2,那该怎么办? "win8.raw1 * 2048 718847 358400 7" 和 "win8.raw2 718848 52426751 25853952 7" - Enkouyami
为什么这个工作即使我们在挂载时没有指定FS? - Jernej Jerin
19更简单的方法是:mount -o loop,offset=$((56 * 512)) sda.img /mnt。来源:http://madduck.net/blog/2006.10.20:loop-mounting-partitions-from-a-disk-image/ - ostrokach
"扇区大小 * 起始 "更好为 512 * 56(而不是 56 * 512)。已编辑。 - n611x007
@JernejJerin mount命令(在Ubuntu和其他发行版中设置)能够自动检测许多文件系统类型,因此通常不需要指定文件系统。 - thomasrutter
当安装时,我建议指定安装点。 - Dicky Tsang
太完美了 :) 像魔法一样顺利!谢谢。 - undefined

Ubuntu 16.04更新:使用新的losetup,现在更容易了。
sudo losetup -Pf disk_image.raw

查看剩下的答案以获取更旧版本的Ubuntu。
一个简单的解决方案是使用kpartx:它会自动识别分区布局并将每个分区映射到一个块设备。之后,你只需要挂载你想要的那个分区。
打开终端,定位磁盘镜像,并输入以下命令:
$ sudo kpartx -av disk_image.raw 
add map loop0p1 (252:2): 0 3082240 linear /dev/loop0 2048
add map loop0p2 (252:3): 0 17887232 linear /dev/loop0 3084288

这将在`/dev/mapper`下创建`loop0p1`和`loop0p2`。从输出中,您可以看到分区的大小,以帮助您识别它们。您可以使用以下命令挂载所需的分区:
$ sudo mount /dev/mapper/loop0p2 /mnt

或者,Nautilus会检测到块设备,并且您可以从侧边栏中挂载它。

enter image description here

当你完成后,卸载你挂载的内容并移除设备映射。
$ sudo umount /mnt
$ sudo kpartx -d disk_image.raw

非常好的答案,快速简单,避免了乘法步骤,很棒。 - Elder Geek
使用sudo apt-get install kpartx命令来安装kpartx以获取访问权限。我个人认为,帖子开头的kpartx链接是一个“陷阱”。含有安装软件暗示的链接是不可取的。 - Hannu
1@Hannu,与软件中心集成的链接是askubuntu上的常见做法,尽管在这种特殊情况下,可以添加典型的图标并更新URL。 - Joni
losetup -Pf之前已经在http://askubuntu.com/a/496576/52975中提到过,我建议您至少链接到该答案。 - Ciro Santilli OurBigBook.com
3请注意,losetup -Pf .. 命令将创建类似于 /dev/loopXpY 的设备,您仍然需要挂载它们。您可以通过查看 losetup 命令的输出来找到 X 的值。Y 是分区编号。 - Gunchars
如@Gunchars所说,sudo losetup -Pf disk_image.raw仅创建了回环设备,但未挂载它!您仍然需要挂载它!可以手动使用mount命令挂载,或者(我更喜欢的方式)使用磁盘图形界面工具选择新创建的回环设备,并通过点击播放按钮(指向右侧的三角形)进行图形化挂载。 - Gabriel Staples
1还要在losetup命令后面加上--show,就像@Ludovic Ronsin在这里(https://askubuntu.com/a/496576/327339)所说的那样,这样你就可以看到正在创建的循环设备号。 - Gabriel Staples
最后,使用losetup -D命令来分离所有的循环设备。 - Gussoh

编辑:适用于util-linux >=2.21。撰写本文时,Ubuntu仅提供版本2.20

来自man losetup

       -P, --partscan
          force kernel to scan partition table on newly created loop device

所以只要运行即可。
$ sudo losetup -f --show -P /path/to/image.img

为了在第一个未使用的循环设备上为磁盘映像的每个分区创建设备节点,并将其打印到标准输出。如果使用/dev/loop0设备,它将至少创建/dev/loop0p1,您可以像往常一样挂载它。

2我在哪里可以找到这个版本的losetup?我在Ubuntu 14.04上的版本有一个来自2003年7月的manpage(util-linux),没有用于扫描分区的-P选项(或其他任何选项)。 - Hannu
1抱歉,我犯了一个错误,我一直在使用Arch Linux中提供的这个选项,它带有更新版本的util-linux软件包。 可惜Ubuntu仍停留在2012年1月发布的版本2.20.1上! --partscan选项是在 util-linux 2.21 中引入的。 - Ludovic Ronsin
1嗯,gnome-disks有一个选项可以挂载磁盘镜像及其分区。(<- 这是用于安装和bash/Terminal使用的,Disks在dash中也能找到它)。 - Hannu
4这应该是被接受的答案... - matthid
@matthid 能改变已接受的答案吗?这个回答很好(而且kpartx的答案实际上依赖于这个版本的losetup),但它几乎比被接受的答案新了三年,而那时候这是正确的做法。 - Auspex
@Auspex OP可以(而且应该!)更改已接受的答案。这是获取分区的现代方式。过去4年来一直如此。 - Navin
@Navin 实际上,自从我写下那句话后,我找到了一个确实被改变的答案,所以我知道这是可以做到的。是的,losetup可能已经存在很长时间了,但即使这个答案也承认,在当时的标准Ubuntu设置中并不是一个选项。 - Auspex

尝试使用gnome-disk-image-mounter:
gnome-disk-image-mounter sda.img

无需sudo。它将被挂载在/media/your_user_name/partition_name,就像USB驱动器一样。

1在16.04上运行得很好。我刚刚安装了一个全新的18.04,这个工具要求输入sudo密码才能访问/dev/loopXX虚拟设备 :( - Laurent

losetup -P 自动化

losetup -P 是从Ubuntu 16.04开始的最佳方法,如https://askubuntu.com/a/496576/52975所述,以下是进一步自动化的功能。用法:

$ los my.img
/dev/loop0
/mnt/loop0p1
/mnt/loop0p2

$ ls /mnt/loop0p1
/whatever
/files
/youhave
/there

$ sudo losetup -l
NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE                                                                                      DIO
/dev/loop1         0      0         0  0 /full/path/to/my.img

$ # Cleanup.
$ losd 0
$ ls /mnt/loop0p1
$ ls /dev | grep loop0
loop0

来源:

los() (
  img="$1"
  dev="$(sudo losetup --show -f -P "$img")"
  echo "$dev"
  for part in "$dev"?*; do
    if [ "$part" = "${dev}p*" ]; then
      part="${dev}"
    fi
    dst="/mnt/$(basename "$part")"
    echo "$dst"
    sudo mkdir -p "$dst"
    sudo mount "$part" "$dst"
  done
)
losd() (
  dev="/dev/loop$1"
  for part in "$dev"?*; do
    if [ "$part" = "${dev}p*" ]; then
      part="${dev}"
    fi
    dst="/mnt/$(basename "$part")"
    sudo umount "$dst"
  done
  sudo losetup -d "$dev"
)

循环模块最大部分配置

这是在16.04之前的一个不错的方法。

loop是一个内核模块,在Ubuntu 14.04中已内置在内核中。

如果你正确地配置它,Linux会自动为你拆分设备。

cat /sys/module/loop/parameters/max_part

说了有多少个分区loop设备可以生成。
在Ubuntu 14.04上,默认情况下是0,这就是为什么没有自动分割发生的原因。
要更改它,我们可以添加:
options loop max_part=31

将文本保存到/etc/modprobe文件中,或者:
GRUB_CMDLINE_LINUX="loop.max_part=31"

打开/etc/default/grub文件,然后执行sudo update-grub命令。

如何设置模块参数也在这里讲解:如何添加内核模块参数?

重启后,执行以下命令:

sudo losetup -f --show my.img

它将镜像挂载到/dev/loopX设备,并自动将分区挂载到/dev/loopXpY设备。

所以,如果你愿意重新启动,这是最方便的方法。

另请参阅


使用losetup命令将整个磁盘镜像附加上去。
# sudo losetup /dev/loop2 sda.img

然后使用mdadm创建一个md设备,所有分区都将创建相应的块设备。
# sudo mdadm --build --level=0 --force --raid-devices=1 /dev/md2 /dev/loop2
mdadm: array /dev/md2 built and started.

现在你应该看到分区设备。
nile-172-b0fef38-76:/mnt/sdb1 # ls -l /dev/md2*
brw-rw---- 1 root disk   9, 2 Oct 10 12:37 /dev/md2
brw-rw---- 1 root disk 259, 0 Oct 10 12:37 /dev/md2p1

这是个有趣的把戏 :) - Johan Boulé
最简单的方法是这样做。谢谢。 - Bahaa Odeh
提示:在使用后删除它们的方法是:mdadm --stop /dev/md2 + mdadm --remove /dev/md2 - undefined

在我看来,最简单的方法是使用mount -o loop,offset=...,就像StackOverflow上的这个答案中提到的那样。其思路如下:
fdisk -l $IMAGE
# calculate the offset in bytes
mount -o loop,offset=$OFFSET $IMAGE $MOUNTPOINT

这种方法是最好的,因为在卸载挂载的分区后不需要删除循环设备。
为了进一步简化任务(如果您经常这样做),您可以使用我的脚本mountimg来为您完成所有操作。只需从https://github.com/AlexanderAmelkin/mountimg获取并按照以下方式使用:
mountimg /media/external_media/sda.img 2 /media/sda_image

你可以选择指定文件系统类型和其他附加的挂载选项,如果你愿意的话。
mountimg /media/external_media/sda.img 2 /media/sda_image -t vfat -o codepage=866,iocharset=utf-8

当你完成分区后,只需使用umount命令卸载它即可。
umount /media/sda_image

这是一种用户友好且互动的方式,需要安装优秀的fzf实用工具以及sudo
首先将此函数添加到您的.bashrc.zshrc文件中:
pmount() { sudo mount -o loop,offset=$(($(sudo fdisk -lu "$1" | sed -n '/^Device/,/^$/p' | tail -n+2 | fzf | sed -E -e 's/[[:blank:]]+/ /g' | cut -d' ' -f2- | sed 's@^[^0-9]*\([0-9]\+\).*@\1@') * 512)) "$1" "$2"; }

然后重新加载您的shell(或输入)。
您可以使用以下命令挂载<.IMG>文件。
pmount my.img /mnt

选择你想要挂载的权限,使用箭头键然后按回车键,弹出一个列表。

enter image description here

使用sudo umount /mnt命令卸载。

1这太棒了!在我的情况下,我的一个分区在BOOT(即第二)列中有一个条目,所以使用cut -f2无法计算$START。为了解决这个问题,如果你的fdisk版本有-o选项,那么你可以用fdisk -l -o Start ${IMG_FILE}轻松地提取Start列。我最终可脚本化的计算$START的版本(不使用交互式的fzf)是fdisk -l -o Start ${IMG_FILE} | tail -n +9 | head -n${PARTITION_NUMBER} | tail -n1 - Nick Crews
1感谢你的建议,Nick Crews。我已经更新了脚本,使其更加健壮(在分区名称后寻找第一个数字)。 - Alexander

当常规方法出现以下错误时,我该如何打开/挂载我的ISO文件? wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error。 我尝试了几种方法,但它们都以某种方式失败了。

实际上,我正在回答这个问题(无法挂载ISO文件),这个问题我也遇到过,并且刚刚解决了,但原始问题已经关闭,并引用了这个问题,尽管它们似乎不同。

我觉得策展人经常因为难以理解的原因关闭问题,然而,我别无选择,只能使用给定的关闭和引用。如果是错误的,也许可以重新打开之前的问题,并将这个答案放在那里,我希望它在那里?由于这个用户编辑了原始问题,我怀疑他可能是关闭原始问题的人:https://askubuntu.com/users/301745/wjandrea

无论如何,抛开文件问题,这里是一个尝试挂载ISO的示例:

$ sudo mount -o ro,loop -t iso9660 nero.iso /mnt
mount: /mnt: wrong fs type, bad option, bad superblock on /dev/loop0, missing codepage or helper program, or other error.

我称之为ISO文件nero.iso,因为使用file命令显示该ISO是"Nero"光盘刻录软件的产物,但这并没有什么帮助。
$ sudo file nero.iso
nero.iso: Nero CD image at 0x4B000 UDF filesystem data (version 1.5) 'nero'

尝试了几种不同的方法后,我偶然发现了一个关于软件 iat 的参考资料,它声称可以将许多CD-ROM映像格式转换为iso9660。哇哦。它立即且轻松地运行起来:
$ sudo apt install iat
$ man iat
$ iat nero.iso out.iso
Iso9660 Analyzer Tool v0.1.3 by Salvatore Santagati
Licensed under GPL v2 or later

Detect Signature ISO9660 START at 339968
Detect Signature ISO9660 END at 342016

 Image offset start at 307200
 Sector header 0 bit
 Sector ECC 0 bit
 Block 2048
Done

真的吗? 现在,mount命令会悄无声息地完成了。
$ sudo mount -o ro,loop out.iso /mnt

嘿,看啊,ISO已经挂载了,Handbrake现在可以愉快地提取内容了。
谢谢,Salvatore Santagati。我一直喜欢咖啡...和冰淇淋。
希望其他遇到这个问题的人能够根据之前问题的参考找到这个答案,尽管文件存档有些隐晦。