缩小 vmdk Virtualbox 磁盘映像

问题描述 投票:0回答:6

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

我从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
行,脚本可以正常工作,但生成的虚拟机大小与以前相同,并且不再启动。

这是 vboxmanage showvminfo "${VM}"

输出
virtualbox
6个回答
34
投票

我找到了解决方案

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

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

在您的主机中,从 VMware 知识库安装 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>

来源


10
投票

我不需要安装 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 中,我选择“选择虚拟硬盘文件”来选择新文件。


8
投票

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

我能够使用他的零命令解决这个问题

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

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

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


2
投票

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

经过一番搜索,我发现此链接附带了 zip https://kb.vmware.com/sfc/servlet.shepherd/version/download/068f4000009EgK0AAK

包含在案例中 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 的评论 - 但我的声誉太低了,所以就在这里。


0
投票

我得到了这个 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


0
投票

只需在 Linux 主机/来宾上使用此开源项目中的 Live CD(此 Live CD 内置了 Zerofree 实用程序;另请阅读网站上的说明):

https://sourceforge.net/projects/live-cd-with-zerofree-utility/

这也将有助于减小导出的虚拟机设备的大小(即 .ova 文件)。

运行 Zerofree 后,请按照此处显示的其余步骤操作:https://stackoverflow.com/a/49499286/21367856以减小虚拟磁盘文件大小。

附注此 Live CD 的 32 位版本( i686 架构)可从以下位置获取: https://sourceforge.net/projects/live-cd-with-zerofree-32-bit/

对于非常旧的架构,请尝试此 Live CD:https://sourceforge.net/projects/live-cd-with-zerofree-x86/

© www.soinside.com 2019 - 2024. All rights reserved.