【问题标题】:Shrink a vmdk Virtualbox disk image收缩 vmdk Virtualbox 磁盘映像
【发布时间】:2015-04-03 07:01:25
【问题描述】:

VirtualBox 能够压缩(减小大小).vdi 图像,但不能使用.vmdk 磁盘图像。但是我们可以压缩.vmdk文件,如果我们:

  1. 分离
  2. 转换为.vdi
  3. 紧凑
  4. 转换回.vmdk
  5. 再次连接到原来的虚拟机

所以我尝试用这个脚本缩小我的 VirtualBox 图像:

#/bin/bash

VM_PATH=~/VirtualBox\ VMs
cd "$VM_PATH"
VM="$(ls ffnord-example_gc-gw0_* -d -1|head -n 1)"
cd "$VM"
VM_VDMK_NAME="$(ls *.vmdk -1|head -n 1)"
VM_NAME="$VM_PATH/$VM/$VM_VDMK_NAME"

echo reducing size of "$VM_NAME"
ls -lah "$VM_NAME"
set -x
vboxmanage showvminfo "${VM}"
vboxmanage storageattach "${VM}" --storagectl SATA --port 0 --device 0 --type hdd --medium none
vboxmanage clonehd --format vdi "${VM_NAME}" /tmp/VM-disk.vdi
vboxmanage closemedium disk "${VM_NAME}" --delete
vboxmanage modifyhd /tmp/VM-disk.vdi --compact
vboxmanage clonehd --format vmdk /tmp/VM-disk.vdi "${VM_NAME}"
vboxmanage closemedium disk /tmp/VM-disk.vdi --delete
vboxmanage storageattach "${VM}" --storagectl SATA --port 0 --device 0 --type hdd --medium 4/VMs/VM-disk1.vmdk

我改编了this script from crysol,但这似乎不适用于 Ubuntu?第一个vboxmanage storageattach 立即以错误开头:

VBoxManage: error: Could not find a controller named 'SATA'

如果我改用"SATA Controller"

vboxmanage storageattach "${VM}" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium none

我收到此错误:

VBoxManage: error: No storage device attached to device slot 0 on port 0 of controller 'SATA Controller'
VBoxManage: error: Details: code VBOX_E_OBJECT_NOT_FOUND (0x80bb0001), component SessionMachine, interface IMachine, callee nsISupports
VBoxManage: error: Context: "DetachDevice(Bstr(pszCtl).raw(), port, device)" at line 381 of file VBoxManageStorageController.cpp

如果我注释掉那些 vboxmanage storageattach 行,脚本可以正常工作,但生成的 VM 大小与以前相同,并且不再启动。

这是output of vboxmanage showvminfo "${VM}"

【问题讨论】:

  • 它是否可能作为 IDE 控制器而不是 SATA 控制器连接到 VM?
  • 您的 VM 没有附加任何存储,这在您发布的 showvminfo 输出中可见。因此,您会看到此错误消息。我怀疑之前的脚本运行不完整,因为第一个 storageattach 命令将 VMDK 文件从您的 VM 配置中分离出来:vboxmanage storageattach [...] --medium none
  • 通过从 VirtualBox 中将虚拟机作为设备导出来实现相当好的收缩。这将创建一个 .ova 文件,它只是一个 TAR 存档,因此可以使用 tar -xvf <appliance>.ova 提取。里面有作为 VMDK 文件的磁盘,比 vboxmanage modifyhd --compact 为 VDI 文件实现的压缩效果更好。

标签: virtualbox


【解决方案1】:

仅供参考: 随着 vmware 对其知识库进行现代化改造,下载链接不再有效。

经过一番搜索,我找到了这个链接 https://kb.vmware.com/sfc/servlet.shepherd/version/download/068f4000009EgK0AAK 附带的 zip

包含在案例中 https://kb.vmware.com/s/article/1023856?lang=en_US&queryTerm=1023856

此外,二进制文件在我的 Ubuntu 中因缺少库而失败,但正在下载 http://archive.ubuntu.com/ubuntu/pool/universe/o/openssl098/libssl0.9.8_0.9.8o-7ubuntu3.1_i386.deb 并安装它很有帮助。

基本上,这个答案应该只是 rubo77 对 Shrink a vmdk Virtualbox disk image 的评论 - 但我的声誉太低了,所以你去吧。

【讨论】:

    【解决方案2】:

    我得到了这个 oooold 脚本,它允许您清除分区上 Windows 内所有不必要的数据。它是用 VBscript 编写的:

        `REM This script is published under the BSD Licence
    REM http://www.opensource.org/licenses/bsd-license.php
    
    Option Explicit
    
    Const sDefaultDir = "C:\"
    Const sDefaultFilename = "overwrite.garbage"
    Const lStartBlockSize = 32768
    
    Call Main
    
    Sub Main()
      Dim sPath, sFilename
      Dim oArgs, oFS, oDrive, oRegExp, oMatches
    
      ShowStartMsg
    
      Set oArgs = WScript.Arguments
      Set oFS = CreateObject("Scripting.FileSystemObject")
    
      If oArgs.Count = 1 Then
        If oArgs(0) = "/?" Then
          ShowHelp true
        End If
      End If
    
      If oArgs.Count > 2 Then
        ShowMsg "ERROR: Invalid command line parameters (too many parameters specified)", true, true
      End If
    
      If oArgs.Count > 0 Then
        sPath = oFS.GetAbsolutePathName(oArgs(0))
      Else
        sPath = ""
      End If
    
      If oFS.FolderExists(sPath) Then
        WScript.Echo "Checking folder " & Chr(34) & sPath & Chr(34) & ": OK"
        If Right(sPath, 1) <> "\" Then
          sPath = sPath & "\"
        End If
      Else
        WScript.Echo "Checking folder " & Chr(34) & sPath & Chr(34) & ": FAILED"
        sPath = sDefaultDir
        WScript.Echo "INFO: Using default folder " & Chr(34) & sPath & Chr(34)
      End If
    
      If oArgs.Count = 2 Then
        sFilename = oArgs(1)
        If sFilename = "" Then
          ShowMsg "ERROR: Filename must not be empty", true, true
        End If
      Else
        sFilename = sDefaultFilename
        WScript.Echo "INFO: Using default filename " & Chr(34) & sFilename & Chr(34)
      End If
    
      Set oRegExp = new RegExp
      oRegExp.Pattern = "[\\\/\:\*\?\" & Chr(34) & "\<\>\|]"
      Set oMatches = oRegExp.Execute(sFilename)
      If oMatches.Count = 0 Then
        WScript.Echo "Validating filename: OK"
      Else
        WScript.Echo "Validating filename: FAILED"
        ShowMsg "ERROR: Filename must not contain the following characters:"_
          & " \ / : * ? " & Chr(34) & " < > |", true, true
      End If
    
      If oFS.FileExists(sPath & sFilename) = False Then
        WScript.Echo "Ensuring that file " & Chr(34) & sFilename & Chr(34) &_
          " does not exist: OK"
      Else
        WScript.Echo "Ensuring that file " & Chr(34) & sFilename & Chr(34) &_
          " does not exist: FAILED"
        ShowMsg "ERROR: File " & Chr(34) & sPath & sFilename & Chr(34) & " already exists", true, true    
      End If
    
      Set oDrive = oFS.GetDrive(oFS.GetDriveName(sPath))
      If UCase(oDrive.FileSystem) = "NTFS" Then
        WScript.Echo "Checking for NTFS: OK"  
      Else
        WScript.Echo "Checking for NTFS: FAILED"
        ShowMsg "ERROR: " & oDrive.FileSystem & " file system not supported", true, true
      End If
    
      Select Case oDrive.DriveType
        Case 1, 2
          WScript.Echo "Checking drive type: OK"
        Case Else
          WScript.Echo "Checking drive type: FAILED"
          Select Case oDrive.DriveType
            Case 3
              ShowMsg "ERROR: Network drives are not supported", true, true
            Case 4
              ShowMsg "ERROR: CD-ROM drives are not supported", true, true
            Case 5
              ShowMsg "ERROR: RAM Disk drives are not supported", true, true
            Case Else
              ShowMsg "ERROR: Unkown drives are not supported", true, true
          End Select
      End Select
    
      If oDrive.FreeSpace > 0 Then
        WScript.Echo "Checking for free space: OK"
      Else
        WScript.Echo "Checking for free space: FAILED"
        WScript.Echo "INFO: No free space available (no action required)"
        ShowMsg "INFO: Exiting Overwrite Script...", false, true    
      End If
    
      WScript.Echo "Creating garbage file " & Chr(34) & sPath & sFilename & Chr(34) & "..."
      CreateGarbageFile sPath & sFilename, oFS
      WScript.Echo "Garbage file successfully created!"
      WScript.Echo "INFO: " & oDrive.AvailableSpace & " byte(s) remained which could not be overwritten"
      WScript.Echo "Deleting garbage file..."
      oFS.DeleteFile sPath & sFilename
      WScript.Echo "Garbage file successfully deleted!"
      WScript.Echo "Exiting Overwrite Script..."
      WScript.Quit
    End Sub
    
    Sub CreateGarbageFile(sAbsFilename, oFS)
      Dim bSngByteBlock
      Dim sBlock
      Dim oFile, oDrive
    
      bSngByteBlock = false
      Set oDrive = oFS.GetDrive(oFS.GetDriveName(sAbsFilename))
      Set oFile = oFS.CreateTextFile(sAbsFilename, false, false)
    
      sBlock = String(lStartBlockSize, 0)
      On Error Resume Next
    
      Do While oDrive.FreeSpace > 0
        If oDrive.FreeSpace < lStartBlockSize Then
          If bSngByteBlock = false Then
            WScript.Echo "INFO: Falling back to single byte block"
            bSngByteBlock = true
            sBlock = String(1, 0)
          End If
        End If
        oFile.Write sBlock
        If Err.Number <> 0 Then
          WScript.Echo "WARNING: Error " & Chr(34) & Err.Description & Chr(34) & " ("_
            & Err.Number & ") occured while writing garbage file"
          Exit Do
        End If
      Loop
    
      On Error GoTo 0
      oFile.Close
    End Sub
    
    Sub ShowStartMsg()
      WScript.Echo "Overwrite Script 1.0 (2004-09-05)"
      WScript.Echo "Copyright (C) 2004 Dennis Dietrich"
      WScript.Echo "http://www.myblog.de/scotty"
      WScript.Echo ""
      WScript.Echo "WARNING: The script is experimental. Use it at your own risk!"
      WScript.Echo "To cancel the execution of this script press CTRL + C"
      WScript.Echo ""
    End Sub
    
    Sub ShowMsg(sMsg, bShowHelpHint, bExit)
      WScript.Echo sMsg
      If bShowHelpHint = True Then
        WScript.Echo ""
        WScript.Echo "Use " & Chr(34) & "CScript Overwrite.vbs /?" & Chr(34) & " to get help."
      End If
      If bExit = True Then
        WScript.Quit
      End If
    End Sub
    
    Sub ShowHelp(bExit)
      WScript.Echo "Cleans free disk space from recoverable data by overwriting it with random"
      WScript.Echo "information. For a higher level of security execute this script at least three"
      WScript.Echo "times. Only NTFS partitions are supported."
      WScript.Echo ""
      WScript.Echo "CScript Overwrite.vbs [path] [filename]"
      If bExit = True Then
        WScript.Quit
      End IF
    End Sub`
    

    (灵感来自http://www.codeproject.com/KB/vbscript/overwrite_script.aspx

    【讨论】:

      【解决方案3】:

      我不需要安装 VMWare 也不需要转换回 VMDK,所以我使用了

      https://scotch.io/tutorials/how-to-create-a-vagrant-base-box-from-an-existing-one#toc-make-the-box-as-small-as-possible

      主机内部:

      sudo yum clean all
      sudo dd if=/dev/zero of=/EMPTY bs=1M
      sudo rm -f /EMPTY
      cat /dev/null > ~/.bash_history && history -c && exit
      

      那么客人关机后:

      $ vboxmanage clonehd --format vdi centos-7-1-1.x86_64.vmdk newdisk.vdi
      $ ls -lh
      -rwx------+ 1 Chloe None  39G Mar 26 14:52 centos-7-1-1.x86_64.vmdk
      -rwx------+ 1 Chloe None  22G Mar 26 15:01 newdisk.vdi
      

      它还允许稍后进行压缩

      $ vboxmanage modifyhd newdisk.vdi --compact
      

      在 VirtualBox GUI 中,我选择了“选择虚拟硬盘文件”来选择新文件。

      【讨论】:

        【解决方案4】:

        我无法让 vmware-vdiskmanager 解决方案之上的 rubo77s 解决方案工作,我相信它依赖于 vmware 工作站或 vmware 播放器,我没有,我确实找到了可执行文件,它给了我错误。

        我可以通过使用他的零命令来解决这个问题

        cat /dev/zero > zero.fill;sync;sleep 1;sync;rm -f zero.fill

        然后使用 virtualboxes 导出到 .ova 工具。

        这将导致 ova 剥离/压缩归零的空间。 然后你可以重新导入它。

        【讨论】:

        • 这对 Windows 10 来宾(导出前的 sdelete.exe)非常有效。从之前导出的 .ova 文件重新导入 vm 后,vmdk 的大小为 80GB,而在 VM 内部,160GB 分区显示 80GB 的可用空间和 160GB 的未使用分区。原始 vmdk 文件的大小约为 300GB 嵌套步骤正在将磁盘转换为 vdi 并像“@Chloe”回答中那样压缩它
        • 在 mac 主机上使用 debian 来宾,我感兴趣的只是导出文件的大小,而且效果很好!
        【解决方案5】:

        我找到了solution

        首先在虚拟机内部用零填充所有空闲空间:

        cat /dev/zero > zero.fill;sync;sleep 1;sync;rm -f zero.fill
        

        在您的主机中,从VMware Knowledge Base 安装 vmware-vdiskmanager:

        cd /tmp/
        wget http://kb.vmware.com/selfservice/viewAttachment.do?attachID=1023856-vdiskmanager-linux.7.0.1.zip&documentID=1023856
        unp 1023856-vdiskmanager-linux-7.0.1.zip
        mv 1023856-vmware-vdiskmanager-linux.7.0.1 /usr/bin/vmware-vdiskmanager
        chmod +x /usr/bin/vmware-vdiskmanager
        

        请注意,在开始之前您有足够的可用磁盘空间,您需要在此过程中将 MV 增长到两倍大小。

        然后压缩它:

        /usr/bin/vmware-vdiskmanager -k ~/VirtualBox\ VMs/<virtual disk.vmdk>
        

        Source

        【讨论】:

        • @Quanlong rubo77 链接的 VMWare 知识库文章末尾的“附件”部分有 3 个版本的 vmware-vdiskmanager。第一个被 Mac OS Finder 识别为 Unix 可执行文件,并且至少在我测试过的 El Capitan 上运行。
        • 无法在 Ubuntu 20 上运行,因为 SSLLoadSharedLibrary: Failed to load library libcrypto.so.0.9.8 并且该版本太旧而无法安装。
        • 要解决“无法加载 libcrypto.so....”,还需要将存档中的“lib”文件夹添加到 LD_LIBRARY_PATH
        • 有趣的是,vmware-vdiskmanager -k 还可以稍微增加 VMDK 磁盘的大小。如果我从 VirtualBox 中将虚拟机作为设备导出,它会创建比 *compacted*(!) VDI 文件更小的 VMDK 文件(大约是 2G VDI 磁盘的 VDI 文件大小的 75%)。如果我对它们运行vmware-vdiskmanager -k,它们会略有增加。
        猜你喜欢
        • 2014-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多