0%

macOS 使用 Vagrant 管理虚拟机

Vagrant 是由 HashiCorp公司开发的构建在 虚拟化技术 之上的虚拟机运行环境管理工具。通过Vagrant可以方便实现的对虚拟机的管理,包括建立和删除虚拟机配置虚拟机运行参数管理虚拟机运行状态自动化配置和安装开发环境必须的各类软件打包和分发虚拟机运行环境等。

关于 Vagrant

Vagrant 是什么

Vagrant的运行,需要依赖某项具体的虚拟化技术。由于 VirtualBox 是一项开源的虚拟化软件,可以同时在Windows、Linux、Macintosh、SSolaris等操作系统上运行并支持众多对众多操作系统的虚拟化,因此,在Vagrant开发的初期,唯一支持的是VirtualBox。随着虚拟化技术的快速发展,现在已经有了更多的虚拟化技术可供选择。VMwareHyperVDocker等都已经可以通过Vagrant的管理而工作。Windows的HyperV技术在部分Windows发行版本中的集成,使得Vagrant在「开盒即用」的特性方面前进了一大步。

因此,Vagrant是 虚拟机管理工具,不是某项具体的虚拟化技术。对于各项虚拟化技术而言,Vagrant提供了一套基于配置文件和命令行的管理工具。也正是因为如此,Vagrant完成了对虚拟化技术在一定程度上的封装。这为将虚拟化技术引入到基于桌面运行环境的开发工作流中创造了便利条件。

为什么要使用 Vagrant

  • 使用Vagrant,可以尽可能避免「Work on my machine」错误,保证所有人的开发环境一致。
  • Vagrant 脚本化配置文件,可以实现开发环境的快速建立。
    • 使用统一的配置文件( vagrantfile )实现对服务器的统一配置。
    • 使用共享文件夹( shared folder )实现代码编辑向服务器的快速提交
    • 使用软件配置脚本( Provisioning scripts )实现服务器上的运行环境的快速建立
    • 拥有标准化的虚拟机分享网络,极大缓解了分享开发环境配置时的网络带宽压力
    • 可以具备一个供安装维护测试使用的可抛弃的服务器端环境。

macOS 配置 Vagrant 环境

如上所说,「Vagrant是虚拟机管理工具,而不是某项具体的虚拟化技术」。既然是管理虚拟机,那么自然需要虚拟机程序和被虚拟的操作系统镜像(Image)。前者常用的选择有VirtualBox和VMWare,后者则包括Ubuntu、FreeBSD等等。Vagrant称前者为provider,称后者为box

  • 安装 VirtualBox

VirtualBox作为一项广泛使用的开源虚拟化软件,理所当然成为我们的首选。在 macOS 上安装 virtualbox 直接去其官网上下载安装即可,具体可以参考 这里

  • 安装 Vagrant
1
$ brew install vagrant
  • 添加镜像
1
2
3
4
5
6
7
$ vagrant box add ubuntu/trusty64
==> box: Loading metadata for box 'ubuntu/xenial64'
box: URL: https://vagrantcloud.com/ubuntu/xenial64
==> box: Adding box 'ubuntu/xenial64' (v20190514.0.0) for provider: virtualbox
box: Downloading: https://vagrantcloud.com/ubuntu/boxes/xenial64/versions/20190514.0.0/providers/virtualbox.box
box: Download redirected to host: cloud-images.ubuntu.com
box: Progress: 1% (Rate: 7173/s, Estimated time remaining: 16:02:42)

ubuntu/trusty64是一个公开 Boxes,运行上面第一行命令后,Vagrant 会在工作目录下创建 Vagrantfile 配置文件。在线下载 Box 会比较慢,你可以先下载 Box 之后,再加载本地的 Box 进行初始化。

这里可以下载到各种系统镜像。

  • 生成虚拟机
1
2
3
4
5
6
7
8
$ mkdir ~/Vagrant/xenial64 && cd ~/Vagrant/xenial64
$ vagrant init ubuntu/xenial64
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
$ ls -a
. .. Vagrantfile

可以看到,执行 vagrant init命令会生成一个 Vagrantfile文件

  • 启动虚拟机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/xenial64'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'ubuntu/xenial64' is up to date...
==> default: A newer version of the box 'ubuntu/xenial64' for provider 'virtualbox' is
==> default: available! You currently have version '20181220.0.0'. The latest is version
==> default: '20200229.0.0'. Run `vagrant box update` to update.
==> default: Setting the name of the VM: xenial_default_1584000787335_65590
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
default: Adapter 1: nat
==> default: Forwarding ports...
default: 22 (guest) => 2200 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
default: SSH address: 127.0.0.1:2200
default: SSH username: vagrant
default: SSH auth method: private key
default: Vagrant insecure key detected. Vagrant will automatically replace
default: this with a newly generated keypair for better security.
default:
default: Inserting generated public key within guest...
default: Removing insecure key from the guest if it's present...
default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
default: The guest additions on this VM do not match the installed version of
default: VirtualBox! In most cases this is fine, but in rare cases it can
default: prevent things such as shared folders from working properly. If you see
default: shared folder errors, please make sure the guest additions within the
default: virtual machine match the version of VirtualBox you have installed on
default: your host and reload your VM.
default:
default: Guest Additions Version: 5.1.38
default: VirtualBox Version: 5.2
==> default: Mounting shared folders...
default: /vagrant => /Users/houmin/Vagrant/xenial
  • SSH 登录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ vagrant ssh
Welcome to Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-140-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

Get cloud support with Ubuntu Advantage Cloud Guest:
http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.

New release '18.04.4 LTS' available.
Run 'do-release-upgrade' to upgrade to it.

vagrant@ubuntu-xenial:~$ ls
  • 关机

Vagrantfile 定制

这里是一个典型的 Vagrantfile 示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.

# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "ubuntu/xenial64"

# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false

# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080

# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"

# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.10"

# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"

# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
config.vm.synced_folder "../data", "/home/vagrant/workspace"

# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
config.vm.provider "virtualbox" do |vb|
# Display the VirtualBox GUI when booting the machine
vb.gui = false
# Customize the amount of memory on the VM:
vb.memory = "2048"
vb.cpus = "2"
end
#
# View the documentation for the provider you are using for more
# information on available options.

# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# SHELL
end

Hostname

1
config.vm.hostname = "cosmos"

Port Mapping

对宿主机器上 8080 端口的访问请求 forward 到虚拟机的 80 端口的服务上:

1
config.vm.network :forwarded_port, guest: 80, host: 8080

Network

Vagrant 有两种方式来进行网络连接:

  • host-only (主机模式)
    • 这种模式下所有的虚拟系统是可以互相通信的,但虚拟系统和真实的网络是被隔离开的,虚拟机和宿主机是可以互相通信的,相当于两台机器通过双绞线互联。
  • Bridge(桥接模式)
    • 该模式下的 VM 就像是局域网中的一台独立的主机,可以和局域网中的任何一台机器通信,这种情况下需要手动给 VM 配 IP 地址,子网掩码等。

我们一般选择 host-only 模式,配置如下:

1
config.vm.network "private_network", ip: "192.168.33.10"

Shared Folder

1
config.vm.synced_folder "../data", "/home/vagrant/workspace"

Provider

1
2
3
4
5
6
7
config.vm.provider "virtualbox" do |vb|
# Display the VirtualBox GUI when booting the machine
vb.gui = false
# Customize the amount of memory on the VM:
vb.memory = "2048"
vb.cpus = "2"
end

Provision

Cloud provisioning is the allocation of a cloud provider’s resources and services to a customer.

Provision是云计算中常见的一个概念,指的是云计算提供商给客户分配资源和服务,Provisioner 也就是资源分配者,在 Vagrant 中可以使用 shell来进行资源分配过程,当然也提供了 dockersalt等其他方式。

Provisioners in Vagrant allow you to automatically install software, alter configurations, and more on the machine as part of the vagrant up process.

下面是一个简单地例子,里面主要配置了一些常用软件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
config.vm.provision "shell", inline: <<-SHELL
set -ex
export DEBIAN_FRONTEND=noninteractive
USER_HOME=/home/vagrant
mkdir -p /home/vagrant/workspace
mkdir -p /home/vagrant/software
PYTHON_VERSION=3.6.6
# use aliyun source
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse' > /etc/apt/sources.list
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse' >> /etc/apt/sources.list
echo 'deb-src http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse' >> /etc/apt/sources.list

# install package
apt-get -yqq update
# install common packages
apt-get install -yqq --no-install-recommends gcc build-essential apt-utils rsync netcat procps libssl-dev
apt-get install -yqq --no-install-recommends vim htop git tree pv libmysqlclient-dev language-pack-zh-hans ack-grep curl
# set git
git config --system push.default simple
git config --system alias.co checkout
git config --system alias.br branch
git config --system alias.ci commit
git config --system alias.st status
git config --system core.editor "vim"
git config --system alias.unstage 'reset HEAD --'
git config --system alias.lg 'log --graph --abbrev-commit --decorate --format=format:"%C(cyan)%h%C(reset) - %C(white)%s%C(reset) %C(yellow)%d%C(reset) %C(dim white) - %anC(reset) %C(dim green)(%ci)%C(reset)" --all'
# set locales
grep -q -F 'LANG=zh_CN.UTF-8' /etc/environment || echo 'LANG=zh_CN.UTF-8' >> /etc/environment
grep -q -F 'LC_ALL=zh_CN.UTF-8' /etc/environment || echo 'LC_ALL=zh_CN.UTF-8' >> /etc/environment
grep -q -F 'LANGUAGE=zh_CN.UTF-8' /etc/environment || echo 'LANGUAGE=zh_CN.UTF-8' >> /etc/environment
# set HOST_IP environment
grep -q -F 'export HOST_IP=$(ifconfig enp0s8 | grep inet | grep -oE "\\b([0-9]{1,3}\\.){3}[0-9]{1,3}\\b" | head -1)' /etc/profile || \
echo 'export HOST_IP=$(ifconfig enp0s8 | grep inet | grep -oE "\\b([0-9]{1,3}\\.){3}[0-9]{1,3}\\b" | head -1)' >> /etc/profile
# set timezone
TZ=Asia/Shanghai
# configure ssh
sed -i "s/PasswordAuthentication no/PasswordAuthentication yes/" /etc/ssh/sshd_config
systemctl restart sshd.service
# clean
apt-get autoremove -yqq --purge
apt-get clean && apt-get autoclean
# set bashrc
grep -q -F "HISTSIZE=1000" $USER_HOME/.bashrc && sed -i 's/^HISTSIZE=1000/HISTSIZE=100000/' $USER_HOME/.bashrc
grep -q -F "HISTFILESIZE=2000" $USER_HOME/.bashrc && sed -i 's/^HISTFILESIZE=2000/HISTFILESIZE=200000/' $USER_HOME/.bashrc
# set prefix sensitive command prompt
echo '"\\e[A": history-search-backward' > $USER_HOME/.inputrc
echo '"\\e[B": history-search-forward' >> $USER_HOME/.inputrc
chown vagrant: $USER_HOME/.inputrc
# config vimrc
echo 'filetype plugin indent on' > $USER_HOME/.vimrc
echo 'set nocompatible' >> $USER_HOME/.vimrc
echo 'filetype off' >> $USER_HOME/.vimrc
echo 'set mouse-=a' >> $USER_HOME/.vimrc
echo 'set fileencodings=utf-8' >> $USER_HOME/.vimrc
echo 'set termencoding=utf-8' >> $USER_HOME/.vimrc
echo 'set fileencoding=utf-8' >> $USER_HOME/.vimrc
echo 'syntax on' >> $USER_HOME/.vimrc
echo 'set nu' >> $USER_HOME/.vimrc
echo 'set tabstop=4' >> $USER_HOME/.vimrc
echo 'set shiftwidth=4' >> $USER_HOME/.vimrc
echo 'set expandtab' >> $USER_HOME/.vimrc
echo 'set cindent' >> $USER_HOME/.vimrc
echo 'set autoindent' >> $USER_HOME/.vimrc
echo 'set showmatch' >> $USER_HOME/.vimrc
echo 'set cursorline' >> $USER_HOME/.vimrc
echo 'set cursorcolumn' >> $USER_HOME/.vimrc
echo 'set incsearch' >> $USER_HOME/.vimrc
echo 'set hlsearch' >> $USER_HOME/.vimrc
echo 'set ignorecase smartcase' >> $USER_HOME/.vimrc
echo 'set nowrapscan' >> $USER_HOME/.vimrc
echo 'set laststatus=2' >> $USER_HOME/.vimrc
echo 'set nostartofline' >> $USER_HOME/.vimrc
echo 'set ruler' >> $USER_HOME/.vimrc
echo ':color desert' >> $USER_HOME/.vimrc
chown vagrant: $USER_HOME/.vimrc
SHELL

问题索引

增加磁盘

为了让虚拟机能够加载新的磁盘,首先我们需要创建磁盘,使用 VBoxManage命令即可。

1
$ VBoxManage createmedium disk --filename mydisk.vmdk --format vmdk --size 40960

通过 VBoxManage命令把磁盘加载到虚拟机的命令如下:

1
$ VBoxManage storageattach myvm --storagectl SCSI Controller --port 2 --device 0 --type hdd --medium mydisk.vmdk

针对这里的几个参数解释如下:

  • myvm 是想要挂载磁盘的虚拟机名,可以通过 VBoxManage命令查看
1
2
3
4
$ VBoxManage list vms
"xenial_default_1584000787335_65590" {7a1ee8ad-2f2a-4433-99d9-15e6e0853962}
"cosmos_default_1584004139557_97080" {c3745cc4-6cea-4868-bca1-ed642722c5a9}
"kernel_default_1584004425866_69721" {394829dd-dc13-4ff2-bee3-02f475d1289a}
  • storagectl指明 Name of the storage controller,这部分信息可以通过下列命令看到
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ VBoxManage showvminfo "kernel_default_1584004425866_69721"
...
Storage Controller Name (0): IDE
Storage Controller Type (0): PIIX4
Storage Controller Instance Number (0): 0
Storage Controller Max Port Count (0): 2
Storage Controller Port Count (0): 2
Storage Controller Bootable (0): on
Storage Controller Name (1): SCSI
Storage Controller Type (1): LsiLogic
Storage Controller Instance Number (1): 0
Storage Controller Max Port Count (1): 16
Storage Controller Port Count (1): 16
Storage Controller Bootable (1): on
SCSI (0, 0): /Users/houmin/VirtualBox VMs/kernel_default_1584004425866_69721/ubuntu-xenial-16.04-cloudimg.vmdk (UUID: 3f4dfd09-b261-460d-8e2f-bd38923fee10)
SCSI (1, 0): /Users/houmin/VirtualBox VMs/kernel_default_1584004425866_69721/ubuntu-xenial-16.04-cloudimg-configdrive.vmdk (UUID: 01c1e2fc-e8a0-41f5-83c6-4bcf4bcaa158)
...

可以看到,这个虚拟机默认支持 IDESCSI两种存储控制器,当前使用SCSI存放了两个磁盘。

进入虚拟机,也可以看到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vagrant@cosmos:~$ sudo fdisk -l
Disk /dev/sdb: 10 MiB, 10485760 bytes, 20480 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes


Disk /dev/sda: 10 GiB, 10737418240 bytes, 20971520 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x602773ce

设备 启动 Start 末尾 扇区 Size Id 类型
/dev/sda1 * 2048 20971486 20969439 10G 83 Linux
  • port指的是存储控制器使用的端口。
  • device指的是 The number of the port's device which is to be modified
  • type 指的是 Define the type of the drive to which the medium is being attached
  • medium 指定对应的磁盘文件

把上述命令对应到 Vagrantfile,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
config.vm.provider "virtualbox" do |vb|
vb.name = "myvm"
vb.memory = 2048
vb.cpus = 2

disk = "mydisk.vmdk"

unless File.exist?(disk)
vb.customize [ "createmedium", "disk", "--filename", disk, "--format", "vmdk", "--size", 1024 * 40 ]
end

vb.customize ['storageattach', :id, '--storagectl', "SCSI", '--port', 0, '--device', 0, '--type', 'hdd', '--medium', disk]
end

注意这里用的是 SCSI而不是IDE,主要是在使用IDE创建的时候,一直没有成功,显示 Timed out while waiting for the machine to boot.

另外,根据上述配置的时候,可能会出现 Could not find a controller named 'SCSI Controller'的问题,参考 GitHub 上的这个 issue,我们知道:

This is not a Vagrant isue.

The issue relies on Virtualbox use different Controller names between os.

In some OS can be IDE Controller but in other is just IDE

1
2
3
4
$ VBoxManage list vms
"c7_host01_1481400784099_26895" {97bec202-de3a-4b06-b790-4aa742671dd0}
$ VBoxManage showvminfo 97bec202-de3a-4b06-b790-4aa742671dd0 | grep 'Storage Controller Name'
Storage Controller Name (0): IDE

To be added

这部分以后会动态更新。

Vagrant 命令备忘

1
2
3
4
5
6
7
8
9
10
11
vagrant box add NAME URL    # 添加一个box
vagrant box list # 查看本地已添加的box
vagrant box remove NAME # 删除本地已添加的box,如若是版本1.0.x,执行vagrant box remove NAME
vagrant init NAME # 初始化,实质应是创建Vagrantfile文件
vagrant up # 启动虚拟机
vagrant halt # 关闭虚拟机
vagrant destroy # 销毁虚拟机
vagrant reload # 重启虚拟机
vagrant package # 当前正在运行的VirtualBox虚拟环境打包成一个可重复使用的box
vagrant ssh # 进入虚拟环境
vagrant status # 查看虚拟机状态

VirtualBox 命令备忘

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
VBoxManage list vms             # 列出所有的虚拟机
VBoxManage list runningvms # 列出所有正在运行的虚拟机
VBoxManage list hdds # 列出VirtualBox当前正在使用的虚拟磁盘的信息
VBoxManage showvminfo <uuid|name> # 显示虚拟机的配置信息
VBoxManage createvm --name "ubuntu" --register # 创建并注册一个虚拟机
VBoxManage modifyvm "ubuntu" --name xenial # 将虚拟机ubuntu重命名为xenial
VBoxManage modifyvm <uuid|name> [--memory <memorysize in MB>] # 修改虚拟机的内存大小
VBoxManage modifyvm win2008 --cpus 2 # 将虚拟机win2008的CPU个数设为2个
VBoxManage modifyvm win2008 --boot1 disk # 将虚拟机的第一启动设备设为硬盘
VBoxManage modifyvm win2008 --nic1 bridged # 将虚拟机win2008的第一个网卡的网络连接方式设为桥接
VBoxManage modifyvm win2008 --nictype1 82540EM # 将虚拟机win2008的第一个网卡的网卡芯片类型设为82540EM
VBoxManage createhd --filename win2008.vdi --size 102400 # 创建一个大小为100G的虚拟硬盘

# 给虚拟机win2008添加一个IDE控制器
VBoxManage storagectl win2008 --name "IDE Controller" --add ide --controller PIIX4

# 将win2008.vdi文件作为虚拟机win2008的第一块IDE硬盘
VBoxManage storageattach win2008 --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium win2008.vdi

# 配置第一个IDE光驱,并挂载安装光盘
VBoxManage storageattach win2008 --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium server_2008_64.iso

# 将主机的/home/vbox目录共享给Guest虚拟机win2008,且共享名为share
VBoxManage sharedfolder add win2008 --name share --hostpath /home/vbox
//该命令必须在关闭虚拟机之后才能执行

# 将主机的/home/vbox目录瞬间共享给Guest虚拟机win2008,且共享名为share
VBoxManage sharedfolder add win2008 --name share --hostpath /home/vbox --transient

备注:使用VBoxManage modifyvm命令的前提是虚拟机已经处于关机状态;

参考资料