草庐IT

linux - 普通 block 设备上的类似 LVM 的快照

coder 2023-06-20 原文

关闭。这个问题是off-topic .它目前不接受答案。












想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。

8 年前关闭。




Improve this question




如果对故事不感兴趣,请跳到问题

在 4 磁盘 raid 5 阵列上不幸丢失了 2 个磁盘后,我陷入了一些巫术,以尽可能多地取回数据。

第一个出现弱点迹象的驱动器被替换,在重建期间(约 80% 通过),第二个驱动器在一些死扇区上出现故障。

长话短说,现在我有两个驱动器(2 和 4)处于一致状态。一 (3) 个已同步,但中间有坏扇区。由于重建过程,最后 (1) 项仅部分同步。
对于总共 4.1 Tb 的阵列,磁盘为 1.5 Tb。

在 234、124 和 1234 配置上尝试了所有只读伏都教之后,我已经能够获得大部分重要数据。 (在 4.1 Tb 整体上只有 100 Gb。)

现在下一步是尝试一些文件系统 (reiserfs) 重建,看看我是否能够获得更多数据。
这些操作是破坏性的。我有三个不同状态的工作磁盘设置要尝试。

所以对于问题

有没有办法制作任何类型的 md block 设备的快照并在不更改 md 设备的情况下进行处理?

几点:

  • 不管性能如何,很慢是可以接受的。
  • 我在外部临时驱动器上有 2 * 2 Tb 的存储空间,可用于快照的“更改日志”。
  • 不要有足够的存储空间将整个设备 (md) 复制到另一个地方并用它制作一个 lvm 卷。 (也没有单独镜像每个驱动器的空间)
  • 不需要及时可靠,数据恢复后(如果有)会删除快照。
  • 好吧,我认为很清楚:我只需要在只读 md 上添加内容,然后将更改扔掉。

  • 有任何想法吗?

    谢谢!

    最佳答案

    使用设备映射器快照目标。请注意,它不会掩盖底层坏磁盘的 I/O 错误,因此这最适合文件系统损坏的好磁盘。

    tl;dr - 跳过我的背景故事的以下三段。

    我最近处理的事件还涉及具有 4 个磁盘但在 USB 外壳中的 RAID5。它被格式化为 NTFS 并具有讽刺意味的是保存了一个 640GB 的磁盘镜像,该镜像是使用 gddrescue 从发生故障的笔记本电脑磁盘中恢复的,在此期间,盒子报告了 300GB 的磁盘故障。我没有执行 ddrescue,所以在我被要求提供帮助之前,坏的笔记本电脑磁盘被送去更换。

    我到达后不得不想办法在我可以访问 RAID 盒的有限时间内检索尽可能多的图像文件。 (它是借来的,我是从外地访问的。)机箱有一个缺陷,在电源循环时它忘记了磁盘故障,因此 RAID 可能运行不同步数天,默默地损坏 NTFS,因此 ntfs-3g拒绝安装它。我设法恢复了 300GB,仅此而已,但这足以恢复图像中包含的许多其他丢失的文件。 (我运行了 testdisk、scrounge-ntfs 和 ntfsundelete,但我选择不使用 photorec。)我最终使用 testdisk 从 NTFS 读取图像文件,但我也尝试使用 testdisk 来修复 NTFS 足以使ntfs-3g 合作,甚至在 VirtualBox 中运行 chkdsk,它只能将图像截断为零字节。

    我发现尝试几种相互排斥的破坏性方法以找到最佳解决方案非常有值(value)。

    设备映射器快照目标使用 dm-snapshot 内核模块,该模块在 block 级别执行写时复制。在我的步骤中,我将对失败的磁盘/dev/failing 进行操作。您需要提供一个足够大的 block 设备来存储我将称之为/dev/cow 的更改。请勿将快照异常存储重新用于您创建的其他写时复制设备,这一点很重要。

     # Make it much harder to accidentally overwrite anything
     # Run on all partition sub-devices as well, if applicable
    1. blockdev --setro /dev/failing
    
     # Create /dev/mapper/top
    2. echo 0 `blockdev --getsz /dev/failing` snapshot /dev/failing /dev/cow p 4 | dmsetup create top
    
     # Manipulate /dev/mapper/top as you wish
    
     # Tear-down
    3. dmsetup remove top
    

    我提供了两种创建/dev/cow 的替代方法:

    A. 使用稀疏文件
     # Create a sparse file
    1. dd if=/dev/zero bs=1048576 count=0 seek=size_in_MB of=tempfile
    
     # Print name of next unused loop device
    2. losetup -f
    
     # Associate the file with a loop device
    3. losetup -f tempfile
    
     # Use as /dev/cow
    
     # Use the name from #2 here
    4. losetup -d /dev/loopX
    
    5. rm tempfile
    

    B. 使用 zram 内核模块(如果适应 ramzswap 或 compcache,请参阅文档!)
     # Create 4 of them - zram0-3 (you may run into a need for more than one)
    1. modprobe zram num_devices=4
    
     # Set size
    2. echo $((1048576*size_in_MB)) > /sys/block/zram0/disksize
    
     # Associate with a loop device (dmsetup will fail with zramX but not loopX!)
    3. losetup -f
    4. losetup -f /dev/zram0
    
     # Use as /dev/cow
    
     # Use the name from #3 here
    5. losetup -d /dev/loopX
    
    6. echo reset > /sys/block/zram0
    

    在我的时间有限的情况下,我需要将 300GB 的图像复制到某个地方,但我没有足够的空间,所以我将其压缩(到 25GB)。

    如果您需要存储 block 设备的压缩只读副本供以后使用而不创建中间文件,我建议使用 squashfs。使用 (un)chunkfs(需要 FUSE)将设备分成 4GB 的 block ,并在每个 block 上单独运行 mksquashfs。这样它就可以存储在 FAT32 卷上,或者存储在 NTFS 上,而不会从 ntfs-3g 创建大文件而导致 CPU 使用率高。我建议对生成的文件进行校验和,如果您想添加冗余,可以尝试 par2。

    为了重新组装设备内容,您很可能需要超过默认的 8 个循环设备。为此, modprobe loop max_loop=2048 或者如果它已编译到您的内核中,则将 max_loop=2048 添加到您的内核命令行。挂载每个 squashfs 并将其中的文件关联到循环设备。最后,使用 dmsetup 使用线性目标将它们连接起来。 (阅读 man dmsetup 并最好记住 -r 开关,否则写入将被删除而不是立即失败。)

    关于linux - 普通 block 设备上的类似 LVM 的快照,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7582019/

    有关linux - 普通 block 设备上的类似 LVM 的快照的更多相关文章

    1. ruby - RSpec - 使用测试替身作为 block 参数 - 2

      我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

    2. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

      我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

    3. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

      我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

    4. ruby-on-rails - openshift 上的 rails 控制台 - 2

      我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

    5. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

      我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

    6. ruby - 在匿名 block 中产生 - 2

      我没有理解以下行为(另请参阅inthisSOthread):defdef_testputs'def_test.in'yieldifblock_given?puts'def_test.out'enddef_testdoputs'def_testok'endblock_test=procdo|&block|puts'block_test.in'block.callifblockputs'block_test.out'endblock_test.calldoputs'block_test'endproc_test=procdoputs'proc_test.in'yieldifblock_gi

    7. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

      在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

    8. ruby - Ruby 中的单 block AES 解密 - 2

      我需要尝试一些AES片段。我有一些密文c和一个keyk。密文已使用AES-CBC加密,并在前面加上IV。不存在填充,纯文本的长度是16的倍数。所以我这样做:aes=OpenSSL::Cipher::Cipher.new("AES-128-CCB")aes.decryptaes.key=kaes.iv=c[0..15]aes.update(c[16..63])+aes.final它工作得很好。现在我需要手动执行CBC模式,所以我需要单个block的“普通”AES解密。我正在尝试这个:aes=OpenSSL::Cipher::Cipher.new("AES-128-ECB")aes.dec

    9. ruby-on-rails - 无法在 Rails 助手中捕获 block 的输出 - 2

      我在使用自定义RailsFormBuilder时遇到了问题,从昨天晚上开始我就发疯了。基本上我想对我的构建器方法之一有一个可选block,以便我可以在我的主要content_tag中显示其他内容。:defform_field(method,&block)content_tag(:div,class:'field')doconcatlabel(method,"Label#{method}")concattext_field(method)capture(&block)ifblock_given?endend当我在我的一个Slim模板中调用该方法时,如下所示:=f.form_field:e

    10. ruby-on-rails - Ruby - 如何从 ruby​​ 上的 .pfx 文件中提取公钥、rsa 私钥和 CA key - 2

      我有一个.pfx格式的证书,我需要使用ruby​​提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o

    随机推荐