问题/解释
我确信我添加的 vagrant box 没有损坏,因为我在 mac 机器上使用过相同的,它工作得很好......
通过执行以下操作,我能够在各种场合重现此问题:
在 macOS 中创建一个 Virtualbox VM(基于 Intel 的 mac 运行任何东西...... Mojave、Catalina、Mojave、Big Sur 等......)
vagrant package --base $VIRTUALBOX_VM_NAME_HERE --output test.box
将.box
文件传输到 Ubuntu
vagrant box add --provider virtualbox --name $VAGRANT_BOX_NAME_HERE test.box
解压错误:
The box failed to unpackage properly. Please verify that the box
file you're trying to add is not corrupted and that enough disk space
is available and then try again.
The output from attempting to unpackage (if any):
x ./include/
x ./include/README.md
x ./include/_Vagrantfile
x ./include/LICENSE
x ./metadata.json
x ./box.ovf
x ./Vagrantfile
x ./info.json
x ./box-disk001.vmdk: gzip decompression failed
bsdtar: Error exit delayed from previous errors.
答案在于错误消息背后的隐藏上下文:
bsdtar: Error exit delayed from previous errors.*
请注意,这vagrant box add ...
是在 Ubuntu 上运行的,并且正在尝试使用 解包,而不是通常的命令。该文件是在 macOS 上创建的,并使用其自己的. 通常,Linux 上的本机文件是使用 GNU 版本的. GNU和 Linux 版本之间有一些重要的区别。bsd
tar
tar
.box
bsdtar
.tar
tar
bsdtar
tar
libarchive
bsdtar
这意味着我们不能期望在所有情况下都在一个平台上创建一个.tar
文件并能够在另一个平台上解压缩它,而没有适当的兼容版本tar
可以处理该文件。该文件没有损坏,只是格式与 Linux 版本bsdtar
预期处理的格式不同。
可以提出vagrant package
旨在创建可移植.box
文件的论点。bsdtar
然而,由于 classic 、libarchive
bsdtar
和 GNU之间的差异tar
,我们最终遇到了不可移植性问题。虚拟机磁盘文件通常使用稀疏文件实现。VirtualBox 使用稀疏文件作为.vmdk
文件格式,以支持动态增长和缩小来宾 VM 磁盘,同时在主机操作系统上仍然保持相对较小。根据您的版本,bsdtar
处理这些稀疏文件的方式不同于其他版本的tar
. Vagrant 使用bsdtar
,但这并不能确保生成的.box
文件在系统之间兼容和完全可移植。MacOS 附带不同版本的bsdtar
比目前在 Ubuntu Linux 上可用。
macOS 大苏尔
$ sw_vers
ProductName: macOS
ProductVersion: 11.6.1
BuildVersion: 20G224
$ ls -l /usr/bin/tar
lrwxr-xr-x 1 root wheel 6 Jan 1 2020 /usr/bin/tar -> bsdtar
$ bsdtar --version
bsdtar 3.3.2 - libarchive 3.3.2 zlib/1.2.11 liblzma/5.0.5 bz2lib/1.0.6
Ubuntu 焦点窝
$ lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Codename: focal
$ tar --version
tar (GNU tar) 1.30
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by John Gilmore and Jay Fenlason.
$ apt-cache show libarchive-tools | grep 'Description-en'
Description-en: FreeBSD implementations of 'tar' and 'cpio' and other archive tools
$ sudo apt-get install libarchive-tools
$ bsdtar --version
bsdtar 3.4.0 - libarchive 3.4.0 zlib/1.2.11 liblzma/5.2.4 bz2lib/1.0.8 liblz4/1.9.2 libzstd/1.4.4
解决方案
我为这个问题找到的一种解决方法是避免使用在 macOS 上.box
创建的文件。vagrant package
除非您还导入到另一台 macOS 机器,.box
否则由于该bsdtar
问题,此文件将无法工作。相反,从$HOME/.vagrant.d/boxes/$VAGRANT_BOX_NAME_HERE
. 这些是裸露的 VirtualBox.ovf
和.vmdk
应该与 Linux 上的 VirtualBox 兼容的文件。一旦这些文件通过您喜欢的任何方法安全地传输到 Linux,它们就可以在那里加载到 VirtualBox 或.vagrant.d/boxes
通过vagrant
命令直接使用。
您有几个选项可以传输文件。我建议使用rsync
来避免tar
&的问题bsdtar
。
# From macOS machine
rsync --progress -av ~/.vagrant.d/boxes/someuser-VAGRANTSLASH-vagrant-box-example-name target-machine.local:~/.vagrant.d/boxes/
# Or... from Linux machine side
rsync --progress -av your-mbp.local:~/.vagrant.d/boxes/someuser-VAGRANTSLASH-vagrant-box-example-name ~/.vagrant.d/boxes/
注意:斜线/
在rsync
源路径和目标路径中很重要! 请参阅此简短rsync
教程以获取使用帮助rsync
传输文件后,请务必检查它们是否相同。我用来shasum -a 256
为文件生成 SHA256 哈希。哈希值应该在两边匹配。
# Check on both machines separately...
cd ~/.vagrant.d/boxes/someuser-VAGRANTSLASH-vagrant-box-example-name/0/virtualbox/
shasum -a 256 box-disk001.vmdk
# Or... use `shasum -c -` and SSH for a one-liner:
# Prints "OK" and exit status 0 if checksums match
( cd ~/.vagrant.d/boxes/someuser-VAGRANTSLASH-vagrant-box-example-name/0/virtualbox/ && shasum -a 256 box-disk001.vmdk ) | ssh exampleuser@your-mbp.local '( cd ~/.vagrant.d/boxes/someuser-VAGRANTSLASH-vagrant-box-example-name/0/virtualbox/ && shasum -a 256 -c - )'
如果您真的想尝试使用[bsd]tar
or.box
文件...
另一种选择是使用gnu-tar
Homebrew将文件重新打包为兼容的.tar
存档。然后将其复制并解压缩到.vagrant.d/boxes
. 我试过了,发现它仍然导致.vmdk
Linux 端的磁盘文件不同。(在两台机器上用sha256sum
perl 或 perl进行检查shasum -a 256
)。
另一种选择是在 Ubuntu 机器上使用bsdtar
from libarchive-tools
package。我试过这个并且能够从vagrant box add
# View .box file contents
bsdtar -v -t -f /path/to/Vagrant_Box/example.box
# Try to extract
mkdir ~/.vagrant.d/boxes/someuser-VAGRANTSLASH-vagrant-box-example-name
cd ~/.vagrant.d/boxes/someuser-VAGRANTSLASH-vagrant-box-example-name
bsdtar -v -x -f /path/to/Vagrant_Box/example.box
x ./include/
x ./include/README.md
x ./include/_Vagrantfile
x ./include/LICENSE
x ./metadata.json
x ./box.ovf
x ./Vagrantfile
x ./info.json
x ./box-disk001.vmdk: gzip decompression failed
bsdtar: Error exit delayed from previous errors.
因此,最好避免使用tar
和bsdtar
跨这些平台,因为它们对box-disk001.vmdk
稀疏文件的处理不兼容。
Vagrant Box 格式内容
正如我们在上面看到的,一个示例.box
解包结构可能类似于以下内容:
/Users/exampleuser/.vagrant.d/boxes/someuser-VAGRANTSLASH-vagrant-box-example-name/
└── 0
└── virtualbox
├── Vagrantfile
├── box-disk001.vmdk
├── box.ovf
├── include
│ ├── LICENSE
│ ├── README.md
│ └── _Vagrantfile
├── info.json
└── metadata.json
3 directories, 8 files
注意:info.json
文件和include
(例如:README.md
、 )下的任何内容_Vagrantfile
都是可选的。这些可以通过vagrant package
选项添加:--vagrantfile
、--info
和--include
。它们不是运行 VM 所必需的。
~/.vagrant.d/boxes/
这些文件可以以相同的结构放入 Ubuntu 机器的文件夹中。确保盒子目录名称与您想要的盒子名称匹配(例如:目录someuser-VAGRANTSLASH-vagrant-box-example-name
= 盒子名称someuser/vagrant-box-example-name
)。
设置一个Vagrantfile
使用盒子名称运行盒子,然后vagrant up
像往常一样运行。
例子:
Vagrant.configure("2") do |c|
c.berkshelf.enabled = false if Vagrant.has_plugin?("vagrant-berkshelf")
c.vm.box = "someuser/vagrant-box-example-name"
c.vm.hostname = "default-vagrant-box-example-name.vagrantup.com"
c.vm.boot_timeout = 1200
c.vm.synced_folder ".", "/vagrant", disabled: true
c.vm.provider :virtualbox do |p|
p.name = "vagrant-box-example-name"
p.customize ["modifyvm", :id, "--audio", "none"]
end
end
macOS 虚拟机笔记
如果有.box
问题的文件是 macOS 虚拟机,那么您可能仍然无法在 Linux 上轻松运行它。原因是 Appleboot.efi
具有特定于 macOS 的启动固件。从技术上讲,不支持在非 Apple 硬件上运行 macOS(你知道……因为资本主义……)。鉴于创建硬件 Hackintosh 机器是可能的,我敢肯定有人已经想通了。我还没有找到让这个工作的方法,但也许其他人知道......