Linux 可以挂载普通的 Time Machine 稀疏捆绑磁盘映像目录吗?

bmi*_*ike 38 linux dmg-image time-capsule time-machine

我想看看 Linux 是否可以通过网络共享挂载和读取本机存储在 Time Capsule 上的文件。像这个问题一样,我正在寻找至少复制hdiutil只读功能的东西,以附加然后安装稀疏捆绑磁盘映像。

SMB 安装很容易,因为 Time Capsule 使用AFPSMB共享,但我不太确定稀疏磁盘包是否可以作为重组的 HFS+ 目录安装。

工作挂载命令或指向解析此 DMG 格式的适当包的指针的奖励积分。

如果不清楚 - 这就是在终端中从 Mac 挂载时带文件的外观,以及我希望 Linux 在无法挂载以大量二进制带文件编码的实际文件系统的情况下看到的内容。

host:iMac.sparsebundle mike$ ls -la
total 24
drwxrwxrwx@     7 mike  staff      264 Jul  5 10:01 .
drwx------      6 mike  staff      264 Mar 26 13:11 ..
-rwxrwxrwx      1 mike  staff      499 Feb 24 15:33 Info.bckup
-rwxrwxrwx      1 mike  staff      499 Feb 24 15:33 Info.plist
drwxrwxrwx  31101 mike  staff  1057390 Jun 17 20:19 bands
-rwxrwxrwx      1 mike  staff      532 Jun 24 22:06 com.apple.TimeMachine.MachineID.plist
-rwxrwxrwx      1 mike  staff        0 Feb 24 15:33 token
host:iMac.sparsebundle mike$ ls -la bands | head -10
total 1582092552
-rwxrwxrwx  1 mike  staff  8388608 Jul  5 08:33 0
-rwxrwxrwx  1 mike  staff  8388608 May 31 13:02 1
-rwxrwxrwx  1 mike  staff  8388608 Jun 24 22:16 10
-rwxrwxrwx  1 mike  staff  8388608 Mar 19 17:15 1000
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 10000
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 10001
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 10002
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 10003
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 10004
host:iMac.sparsebundle mike$ ls -la bands | tail -10
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:51 fff6
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:51 fff7
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:51 fff8
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:51 fff9
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:51 fffa
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 fffb
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 fffc
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 fffd
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 fffe
-rwxrwxrwx  1 mike  staff  8388608 May 31 00:50 ffff
host:~ mike$ ls -la bands|wc -l
   96636
Run Code Online (Sandbox Code Playgroud)

小智 39

您可以结合使用这两者:

用于读取 Mac OS 稀疏捆绑磁盘映像的 FUSE 文件系统

Apple 的 Time Machine 熔断只读文件系统

第一个处理 .sparsebundle 格式,将其呈现为 dmg 文件,然后可以像正常一样挂载。第二个负责 Time Machine 使用的目录硬链接。


tha*_*min 5

这是@TorArneVestbø 答案的扩展。

安装https://github.com/torarnv/sparsebundlefshttps://github.com/abique/tmfs 后,您需要在 Bash 中运行以下脚本。确保在开始时将两个变量更新为源和目标。

SB="/path/to/your/Backup.sparsebundle"
TM_MNT="/path/to/where/to/mount"

# Make directories
mkdir -p "$TM_MNT"
SB_MNT=`mktemp --tmpdir -d sparsebundle_mnt.XXX`
SB_DMG="$SB_MNT/sparsebundle.dmg"
HFS_MNT=`mktemp --tmpdir -d hfsx_mnt.XXX`

# Mount the sparse bundle
sudo `which sparsebundlefs` "$SB" "$SB_MNT"

# Mount the HFS+ partition
OFF=`sudo parted "$SB_DMG" unit B print | tr 'B' ' ' | awk '/hfsx/ {print $2}'`
SZ=`sudo parted "$SB_DMG" unit B print | tr 'B' ' ' | awk '/hfsx/ {print $4}'`
LO=`sudo losetup -f "$SB_DMG" --offset $OFF --sizelimit $SZ --show`
sudo mount -t hfsplus -r "$LO" "$HFS_MNT"

# Mount the Time Machine filesystem
sudo `which tmfs` "$HFS_MNT" "$TM_MNT" -ouid=$(id -u $USER),gid=$(id -g $USER),allow_other
Run Code Online (Sandbox Code Playgroud)

您可以访问最终安装(只要您可以访问$TM_MNT)。如果 FUSE 未设置为允许其他用户,最后一行可能会失败,它会告诉您如何修复它。

要卸载,您需要执行以下操作:

sudo umount "$TM_MNT"
sudo rmdir "$TM_MNT"
sudo umount "$HFS_MNT"
sudo rmdir "$HFS_MNT"
sudo losetup -d "$LO"
sudo umount "$SB_MNT"
sudo rmdir "$SB_MNT"
Run Code Online (Sandbox Code Playgroud)

这已在 Fedora 28 系统上进行了测试,并且运行良好。


小智 5

较新的 MacOS 版本不使用 HFS+ 作为 Time Machine 稀疏包的底层 FS,而是使用 APFS。APFS 的优点是它本身(如:在 FS 本身内部)支持快照。

\n

这是一个完整的教程,在 Fedora Workstation 33 上进行了测试和运行,介绍了如何在 SMB 上挂载 MacOS Time Machine 备份文件夹,然后挂载 Sparsebundle,然后挂载 APFS 文件系统并访问所有快照。

\n

如何将 Mac Time Machine 备份稀疏目录(在 SMB 上)安装为 Linux 上的可浏览文件系统

\n

本指南在 Fedora 33 上进行了测试。

\n

先决条件

\n

我们需要sparsebundlefs将sparsebundle 目录挂载为DMG 磁盘映像。此外,我们还需要 APFS 熔断驱动程序和用户空间实用程序来将 Mac APFS 分区挂载到 DMG 文件内。通过apfsutil二进制文件,我们甚至可以浏览 APFS 分区内的快照。

\n
# we assume the directory /usr/local/bin exists and is in the path\n\n# become root\nsudo su\n\n# install sparsebundlefs (https://github.com/torarnv/sparsebundlefs)\nyum -y install fuse-devel\ncd\ngit clone https://github.com/torarnv/sparsebundlefs.git\ncd sparsebundlefs\nmake\nmv sparsebundlefs /usr/local/bin\n\n# install apfs-fuse (https://github.com/sgan81/apfs-fuse, https://linuxnewbieguide.org/how-to-mount-macos-apfs-disk-volumes-in-linux/)\nyum -y install bzip2-devel fuse3-devel\ncd\ngit clone https://github.com/sgan81/apfs-fuse.git\ncd apfs-fuse\ngit submodule init\ngit submodule update\nmkdir build\ncd build\ncmake ..\nmake\nmv apfs* /usr/local/bin\nln -s /usr/local/bin/apfs-fuse /usr/sbin/mount.apfs\n
Run Code Online (Sandbox Code Playgroud)\n

脚本

\n

mount_timebackup.sh创建一个包含以下内容的文件。别忘了chmod +x

\n
#!/usr/bin/env bash\n\n# mount_timebackup.sh\n\n## CHANGE VARIABLES HERE\nSMB_PATH="\\\\\\\\server_name_or_ip_address/share"\nSMB_USERNAME="some_username"\nSMB_PASSWORD="some_password"\n## --END--\n\nSMB_MNT="/mnt/timebackup_sparsebundle"\nSMB_OPTIONS="user=${SMB_USERNAME},pass=${SMB_PASSWORD},ro"\nSB_MNT="/mnt/sparsebundlefs"\nSB_DMG="${SB_MNT}/sparsebundle.dmg"\nAPFS_MNT="/mnt/apfs"\n\n# Check availability of binaries\nSBFS_BIN="$(which sparsebundlefs)"\nif [[ -z "${SBFS_BIN}" ]]; then echo "[!] sparsebundlefs binary not found, aborting."; exit 1; fi\n\nPARTED_BIN="$(which parted)"\nif [[ -z "${PARTED_BIN}" ]]; then echo "[!] parted binary not found, aborting."; exit 1; fi\n\nLOSETUP_BIN="$(which losetup)"\nif [[ -z "${LOSETUP_BIN}" ]]; then echo "[!] losetup binary not found, aborting."; exit 1; fi\n\nAPFSUTIL_BIN="$(which apfsutil)"\nif [[ -z "${APFSUTIL_BIN}" ]]; then echo "[!] apfsutil binary not found, aborting."; exit 1; fi\n\n# Make directories\nmkdir -p "${SMB_MNT}" 2>/dev/null\nmkdir -p "${SB_MNT}" 2>/dev/null\nmkdir -p "${APFS_MNT}" 2>/dev/null\n\n# Mount SMB share\nif ! grep -q ${SMB_MNT} /proc/mounts\nthen\n    echo "[i] Mounting share \\"${SMB_PATH}\\" as user ${SMB_USERNAME} on ${SMB_MNT}..."\n    if ! mount.cifs "${SMB_PATH}" "${SMB_MNT}" -o "${SMB_OPTIONS}"\n    then\n        echo "[!] Error mounting SMB share, check output. Aborting."\n        exit 1\n    fi\nelse\n    echo "[i] SMB share ${SMB_PATH} found on ${SMB_MNT}..."\nfi\n\n# Mount the sparse bundle\nif ! grep -q ${SB_MNT} /proc/mounts\nthen\n    echo "[i] Finding sparsebundle directory..."\n    SB="$(find "${SMB_MNT}" -maxdepth 1 -type d -name '*.sparsebundle')"\n\n    if [[ -z "${SB}" ]]\n    then\n        echo "[!] Sparsebundle directory not found under $SMB_MNT, aborting."\n        exit 1\n    fi\n\n    echo "[i] Mounting sparsebundle directory \\"${SB}\\" as sparsebundle filesystem on ${SB_MNT}..."\n    if ! "${SBFS_BIN}" "$SB" "$SB_MNT"\n    then\n        echo "[!] Error mounting sparsebundlefs, check output. Aborting."\n        exit 1\n    fi\nelse\n    echo "[i] Sparsebundle mount found on ${SB_MNT}..."\nfi\n\n# Mount the APFS partition as loopback device\nLO="$("${LOSETUP_BIN}" | grep "${SB_MNT}" | awk '{print $1}')"\nif [[ -z "${LO}" ]]\nthen\n    echo "[i] Determining characteristics of APFS filesystem inside ${SB_DMG}..."\n    OFF="$("${PARTED_BIN}" "${SB_DMG}" unit B print 2>/dev/null | tr 'B' ' ' | awk '/disk image/ {print $2}')"\n    SZ="$("${PARTED_BIN}" "${SB_DMG}" unit B print 2>/dev/null | tr 'B' ' ' | awk '/disk image/ {print $4}')"\n\n    if [[ -z "${OFF}" ]] || [[ -z "${SZ}" ]]\n    then\n        echo "[!] Unable to determine APFS filesystem offset and size characteristics, aborting."\n        exit 1\n    fi\n\n    echo "Mounting APFS filesystem inside ${SB_DMG} from offset ${OFF} with max size ${SZ} on loopback device..."\n    LO="$("${LOSETUP_BIN}" -f "${SB_DMG}" --offset ${OFF} --sizelimit ${SZ} --show)"\n    if [[ -z "${LO}" ]]\n    then\n        echo "[!] Error mounting APFS filesystem, aborting."\n        exit 1\n    fi\nelse\n    echo "[i] APFS filesystem found at ${LO}."\nfi\n\n# List snapshots\necho "[i] Listing available snapshots in the APFS filesystem at ${LO}:"\n"${APFSUTIL_BIN}" "${LO}"\n\necho "[i] To mount the latest available snapshot, run:"\necho "    mount.apfs \\"${LO}\\" \\"${APFS_MNT}\\""\necho\necho "[i] To mount a specific snapshot, run:"\necho "    mount.apfs -o snap=XXXXX \\"${LO}\\" \\"${APFS_MNT}\\""\n
Run Code Online (Sandbox Code Playgroud)\n

用法

\n

编辑该mount_timebackup.sh文件并输入 SMB 路径、用户名和密码。\n然后运行该脚本。它将显示如下内容:

\n
14:07 \xe2\x98\x85root(su)@fedora /root/bin\n0\xc2\xbb ./mount_timebackup.sh\n[i] Mounting share "\\\\192.168.1.1/My_Timebackup" as user edward on /mnt/timebackup_sparsebundle...\n[i] Finding sparsebundle directory...\n[i] Mounting sparsebundle directory "/mnt/timebackup_sparsebundle/edward.sparsebundle" as sparsebundle filesystem on /mnt/sparsebundlefs...\n[i] Determining characteristics of APFS filesystem inside /mnt/sparsebundlefs/sparsebundle.dmg...\nMounting APFS filesystem inside /mnt/sparsebundlefs/sparsebundle.dmg from offset 209735680 with max size 22685610287104 on loopback device...\n[i] Listing available snapshots in the APFS filesystem at /dev/loop0:\nVolume 0 B2853571-BC03-4DCC-91B7-295D046776BF\n---------------------------------------------\nRole:               Backup\nName:               Reservekopiee\xcc\x88n van Edward (Case-sensitive)\nCapacity Consumed:  177614307328 Bytes\nFileVault:          No\nSnapshots:\n    587 : 'com.apple.TimeMachine.2021-05-27-131216.backup'\n    3122 : 'com.apple.TimeMachine.2021-06-03-142024.backup'\n    5354 : 'com.apple.TimeMachine.2021-06-10-185257.backup'\n    7193 : 'com.apple.TimeMachine.2021-06-17-210159.backup'\n    8278 : 'com.apple.TimeMachine.2021-06-24-135457.backup'\n    10556 : 'com.apple.TimeMachine.2021-07-01-221410.backup'\n    12345 : 'com.apple.TimeMachine.2021-07-09-155806.backup'\n    13326 : 'com.apple.TimeMachine.2021-07-17-074435.backup'\n    13747 : 'com.apple.TimeMachine.2021-07-24-112952.backup'\n    16670 : 'com.apple.TimeMachine.2021-07-31-085515.backup'\n    17164 : 'com.apple.TimeMachine.2021-08-25-112049.backup'\n    19466 : 'com.apple.TimeMachine.2021-09-01-202809.backup'\n    21613 : 'com.apple.TimeMachine.2021-09-08-200654.backup'\n    24023 : 'com.apple.TimeMachine.2021-09-15-202105.backup'\n    25807 : 'com.apple.TimeMachine.2021-09-23-194219.backup'\n    27372 : 'com.apple.TimeMachine.2021-09-30-161110.backup'\n    29229 : 'com.apple.TimeMachine.2021-10-08-064900.backup'\n    30021 : 'com.apple.TimeMachine.2021-10-14-222820.backup'\n    30260 : 'com.apple.TimeMachine.2021-10-22-132638.backup'\n    33163 : 'com.apple.TimeMachine.2021-10-30-141729.backup'\n    36728 : 'com.apple.TimeMachine.2021-11-06-102305.backup'\n    40140 : 'com.apple.TimeMachine.2021-11-13-201741.backup'\n    41362 : 'com.apple.TimeMachine.2021-11-21-100951.backup'\n    42977 : 'com.apple.TimeMachine.2021-11-28-212032.backup'\n    45488 : 'com.apple.TimeMachine.2021-12-06-155539.backup'\n    48657 : 'com.apple.TimeMachine.2021-12-13-154439.backup'\n    50554 : 'com.apple.TimeMachine.2021-12-20-084732.backup'\n    51856 : 'com.apple.TimeMachine.2022-02-06-105522.backup'\n    54178 : 'com.apple.TimeMachine.2022-02-13-215427.backup'\n    57082 : 'com.apple.TimeMachine.2022-02-21-151624.backup'\n    58494 : 'com.apple.TimeMachine.2022-03-06-155624.backup'\n    60265 : 'com.apple.TimeMachine.2022-03-13-124536.backup'\n    64198 : 'com.apple.TimeMachine.2022-03-20-160040.backup'\n    67262 : 'com.apple.TimeMachine.2022-03-25-173848.backup'\n    68136 : 'com.apple.TimeMachine.2022-03-26-233827.backup'\n    69024 : 'com.apple.TimeMachine.2022-03-28-165918.backup'\n    69886 : 'com.apple.TimeMachine.2022-03-29-164136.backup'\n    70515 : 'com.apple.TimeMachine.2022-03-30-194139.backup'\n    70869 : 'com.apple.TimeMachine.2022-04-01-014510.backup'\n    72140 : 'com.apple.TimeMachine.2022-04-02-082134.backup'\n    72965 : 'com.apple.TimeMachine.2022-04-08-204109.backup'\n    73092 : 'com.apple.TimeMachine.2022-04-10-194926.backup'\n    73745 : 'com.apple.TimeMachine.2022-04-11-204535.backup'\n    74595 : 'com.apple.TimeMachine.2022-04-12-204033.backup'\n    75319 : 'com.apple.TimeMachine.2022-04-13-190833.backup'\n    75971 : 'com.apple.TimeMachine.2022-04-14-222526.backup'\n    77237 : 'com.apple.TimeMachine.2022-04-16-083710.backup'\n    77319 : 'com.apple.TimeMachine.2022-04-17-094739.backup'\n    77619 : 'com.apple.TimeMachine.2022-04-18-090536.backup'\n    77705 : 'com.apple.TimeMachine.2022-04-18-104921.backup'\n    77825 : 'com.apple.TimeMachine.2022-04-19-225314.backup'\n    78369 : 'com.apple.TimeMachine.2022-04-20-171232.backup'\n    78469 : 'com.apple.TimeMachine.2022-04-20-190918.backup'\n    78598 : 'com.apple.TimeMachine.2022-04-20-203829.backup'\n    78668 : 'com.apple.TimeMachine.2022-04-20-220645.backup'\n    78794 : 'com.apple.TimeMachine.2022-04-21-155554.backup'\n    79746 : 'com.apple.TimeMachine.2022-04-30-101539.backup'\n    79836 : 'com.apple.TimeMachine.2022-04-30-112852.backup'\n    79863 : 'com.apple.TimeMachine.2022-04-30-114329.backup'\n    79937 : 'com.apple.TimeMachine.2022-04-30-122935.backup'\n    80049 : 'com.apple.TimeMachine.2022-05-01-083701.backup'\n    80131 : 'com.apple.TimeMachine.2022-05-01-093828.backup'\n    80253 : 'com.apple.TimeMachine.2022-05-01-110758.backup'\n    80289 : 'com.apple.TimeMachine.2022-05-01-122415.backup'\n\n[i] To mount the latest available snapshot, run:\n    mount.apfs "/dev/loop0" "/mnt/apfs"\n\n[i] To mount a specific snapshot, run:\n    mount.apfs -o snap=XXXXX "/dev/loop0" "/mnt/apfs"\n
Run Code Online (Sandbox Code Playgroud)\n

卸载

\n
# as root, in this specific order\numount /mnt/apfs\nlosetup -D\numount /mnt/sparsebundlefs\numount /mnt/timebackup_sparsebundle\n
Run Code Online (Sandbox Code Playgroud)\n