ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用命令行管理虚拟机:从VBoxManage到virsh的实践指南

用命令行管理虚拟机:从VBoxManage到virsh的实践指南 1. 为什么最终要把虚拟机操作搬进终端这两年我管理虚拟机的方式已经从图形界面迁移到了命令行工具。三十多台虚拟机散落在几台没有显示器的宿主机上日常操作不是敲命令就是写脚本让任务自己跑。如果你也遇到过这种场景批量创建几台测试虚拟机、给一整个环境打快照、在深夜通过SSH远程重启一台卡死的虚机你多半能理解我为什么坚持用命令行。1.1 先说说我当初为什么受够了图形界面早年在Windows上用VMware Workstation折腾虚拟机每次创建新虚机都要打开向导一步一步选系统类型、分配内存、创建虚拟磁盘点得再熟练也要一两分钟。赶上一次要部署五台环境一致的测试机光在向导里点来点去就耗掉了将近一个小时然后还要逐台登录系统改主机名、改IP。那个年代最烦的事是GUI窗口一多分辨不清哪台是哪个项目误操作关机或者误删快照的事我干过不止一次。后来接触了VirtualBox发现它自带的VBoxManage其实能力极强几乎所有GUI里能做的事情命令行都能做而且做得更快。再后来管理Linux服务器上的KVM虚拟机图形工具基本不可用只能依赖virsh。从那以后我明确了一个结论GUI适合单机少量操作、边看边弄的场景命令行才是批量化、自动化、无头运维的正解。1.2 命令行工具的三个不可替代优势第一可重复、可版本化。我在项目里把创建虚拟机的命令整理成Shell脚本扔进Git仓库。新同事入职拉下来跑一遍五分钟内得到一套和团队其他人完全一致的环境。这是GUI永远做不到的——你总不能把“鼠标点的每一步”录下来给同事跑。第二天然适合远程和无头环境。宿主机往往没有显示器、没有桌面环境或者远在机房你只有SSH终端。这种情况下图形界面根本无从谈起而virsh、VBoxManage这一类工具就是为终端而生的。启动、关机、查状态、打快照全在一个SSH会话里完成。第三便于批处理和复合操作。命令行可以和for循环、cron定时任务、监控告警系统组合使用。比如每天早上8点自动给测试环境打一个快照代码里几行搞定哪怕你人在休假它也会按计划执行。1.3 什么场景继续用GUI什么场景必须命令行我不是建议把图形界面一棍子打死。偶尔需要直观确认虚拟机的显示画面、调试一个只有图形界面才能复现的UI问题我会开GUI看一眼。但凡是环境准备、批量部署、网络配置、快照备份、模板克隆这类操作我都建议走命令行。理由很简单这些操作重复度高、出错代价大、逻辑固定最适合交给脚本去保证一致性。如果你刚开始接触虚拟机命令行可能觉得一堆参数很唬人。其实它没有那么难无非是“先创建什么、再挂载什么、最后启动什么”的顺序问题。我下面把实践中的经验拆开讲选哪套工具、命令怎么写、踩过哪些坑尽量一次说清楚。2. 三套主流命令行工具到底该学哪个市面上能管理虚拟机的命令行工具不少但真正日常高频用到的我体感就三套VirtualBox的VBoxManage、VMware Workstation/Player配套的vmrun、Linux下KVM/libvirt体系里的virsh。它们的定位和适用场景差别挺大我建议你先按自己的主力平台来选。2.1 VBoxManage跨平台免费方案里的全能选手VBoxManage是VirtualBox的命令行入口。它最大的优势是免费、跨平台Windows、macOS、Linux上都能用而且功能覆盖极其完整建磁盘、建虚机、改配置、挂ISO、配网络、打快照、克隆、导出导入GUI里有的功能命令基本都有。macOS上我特别推荐这套组合比如在Apple Silicon Mac上装好VirtualBox后用VBoxManage创建虚机配合headless模式跑Linux体验很干净。使用前把VirtualBox的安装目录加入PATHWindows一般是C:\Program Files\Oracle\VirtualBoxmacOS/Linux则取决于安装方式。基本命令格式非常统一所有操作都是一条VBoxManage子命令# 列出所有虚拟机含关机状态 VBoxManage list vms # 列出正在运行的虚拟机 VBoxManage list runningvms # 查看某一台机器的详细配置 VBoxManage showvminfo ubuntu-test2.2 vmrunVMware生态里的命令行接口VMware Workstation最初带的是vmrun这工具给人的感觉是“有但不太起眼”因为大多数人装完VMware根本不碰它。可一旦你开始管理多台.vmx虚拟机就会发现vmrun非常顺手。它所在的位置是VMware Workstation的安装目录比如Windows下通常在C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe。macOS版VMware Fusion则把它放在了/Applications/VMware Fusion.app/Contents/Library/。vmrun最常用的操作是远程开关虚机、打快照、在客户机里执行命令# 列出当前运行中的虚拟机 vmrun list # 无界面模式启动虚拟机 vmrun start /path/to/linux.vmx nogui # 停止虚拟机 vmrun stop /path/to/linux.vmx # 打快照 vmrun snapshot /path/to/linux.vmx clean-state # 回滚快照 vmrun revertToSnapshot /path/to/linux.vmx clean-state注意一点VMware Workstation Pro自17版本之后面向个人用户免费VMware官方就建议用vmrun来做命令行管理。如果你主力是VMware系列学会vmrun不吃亏。2.3 virshLinux服务器上KVM的管理标配如果你管理的是机房里的Linux物理机上面用KVM做虚拟化那遇到的一定是virsh。它是libvirt提供的Shell工具用起来远比直接调用qemu命令安全因为libvirt会把存储、网络、CPU、内存这些资源统一管起来。# 查看所有虚机状态 virsh list --all # 启动一台虚机 virsh start ubuntu-test # 平滑关机虚拟机内执行ACPI关机 virsh shutdown ubuntu-test # 强制断电 virsh destroy ubuntu-test # 查看虚机的XML配置 virsh edit ubuntu-test我个人的建议是桌面开发环境优先VBoxManageWindows上既有VMware订阅或习惯VMware系列则看vmrun服务器生产环境直接virsh。三套工具的哲学很像学会一套另外两套上手成本很低。工具所属生态适用平台跨平台远程管理快照/克隆VBoxManageOracle VirtualBoxWindows/macOS/Linux支持弱靠系统SSH支持vmrunVMware Workstation/FusionWindows/macOS/Linux支持弱靠vSphere或SSH支持virshKVM/libvirtLinux为主不支持UI强可连远程libvirt支持3. 用命令行从零创建并启动一台Linux虚机理论说再多不如完整走一遍流程。下面我用VirtualBox的VBoxManage做演示从零创建一台CentOS Stream虚拟机包括虚拟硬盘、系统配置、挂载ISO、端口转发、免图形界面启动。你在自己机器上照着敲基本是能直接跑通的。3.1 准备工作镜像下载与目录规划先准备好Linux系统镜像比如CentOS Stream 9或者Ubuntu Server ISO官方站点下载即可。再规划一下虚拟磁盘存放位置我习惯单独建一个目录比如~/VirtualBoxData/方便统一备份和清理。创建虚机最忌讳的是“想到哪做到哪”命令执行一半发现目录不对、磁盘文件散落在各处后面脚本化运维会很痛苦。所以我会先创建一个与虚机同名的目录mkdir -p ~/VirtualBoxData/centos-dev cd ~/VirtualBoxData/centos-dev3.2 创建虚拟硬盘注册虚机创建虚机其实分两步先建虚拟硬盘文件再创建并注册虚机本身。很多人第一次用命令行时搞不清这两者的区别误把“创建虚机”理解为一个命令完成所有事。# 创建一块30GB的动态扩展虚拟硬盘 VBoxManage createhd --filename centos-dev.vdi --size 30720 --variant Standard # 创建一台不注册的虚机先建后注册也可以 VBoxManage createvm --name centos-dev --ostype RedHat_64 --register这里的--ostype参数建议填上它会影响虚拟机的默认硬件配置和推荐参数。--register选项的作用是把虚机注册进VirtualBox虚拟机列表中这样后续所有VBoxManage命令才能按名字找到它。如果你用KVM的virsh对应的是virt-install它更自动化直接一条命令完成磁盘创建、CPU内存分配、网络接入和介质挂载。小规模管理我反而喜欢VBoxManage这种分步方式每一步干什么清清楚楚出错时排查也容易。3.3 配置CPU、内存挂载ISO镜像虚机创建好之后接下来是配置硬件。这一步的参数直接影响系统安装后的流畅度所以我通常先看一眼宿主机资源再定内存至少分4GBCPU给2核显存16MB够纯命令行Linux使用。# 分配2核CPU和4GB内存 VBoxManage modifyvm centos-dev --cpus 2 --memory 4096 --vram 16 # 添加SATA控制器 VBoxManage storagectl centos-dev --name SATA --add sata --controller IntelAhci # 把虚拟硬盘挂载到SATA端口0 VBoxManage storageattach centos-dev --storagectl SATA --port 0 --device 0 --type hdd --medium centos-dev.vdi # 把系统ISO挂载到光驱即SATA端口1 VBoxManage storageattach centos-dev --storagectl SATA --port 1 --device 0 --type dvddrive --medium /path/to/CentOS-Stream-9-latest-x86_64-dvd1.iso注意storageattach里有个细节--medium填ISO文件的绝对路径。如果你挂载一个空光驱需要写成--medium emptydrive。挂载错误导致开机找不到ISO是我见过最多的新手翻车现场。设置启动顺序也很关键。默认顺序通常是软驱、光驱、硬盘如果你希望它从ISO启动安装可以显式指定VBoxManage modifyvm centos-dev --boot1 dvd --boot2 disk --boot3 none --boot4 none3.4 headless模式下启动绕过图形界面其实到这里一条VBoxManage startvm centos-dev就能弹出一个虚拟机窗口。但命令行使用场景下我几乎总是用headless方式启动即让虚拟机在后台运行不显示窗口。这在宿主机没有桌面环境、或者你通过SSH远程管理时是唯一选择。VBoxManage startvm centos-dev --type headless启动后看不到安装画面怎么办答案是串口或VNC。KVM里可以加VNC图形端口VirtualBox则可以通过RDP远程桌面连接不过需要扩展包支持。日常我更习惯的做法是在安装系统前先配置好网络和SSH端口转发装完系统直接通过SSH进去操作完全不需要见图形界面。3.5 配置NAT端口转发让主机能直接SSH进去VBoxManage里默认的nic1是NAT模式虚拟机可以上网但宿主机访问不到虚机内部。解决办法是给NAT网卡添加端口转发规则把宿主机的2222端口转发到虚拟机的22端口。# 设置第一块网卡为NAT模式 VBoxManage modifyvm centos-dev --nic1 nat # 添加端口转发规则宿主机2222端口 - 虚机22端口 VBoxManage modifyvm centos-dev --natpf1 ssh,tcp,,2222,,22这样宿主机上执行ssh -p 2222 user127.0.0.1就能直接登录虚机了。端口转发规则在VBoxManage里非常实用等你看完下一章的Nginx多站点场景会发现它其实是整个开发环境的核心枢纽。3.6 VMware和KVM里对应的“一条龙”操作如果你是VMware生态创建虚拟机没有VirtualBox这种“先建硬盘、再配硬件”的分步感更常用的是直接复制.vmx模板然后用vmrun start启动。若用KVM的virt-install则可以把磁盘创建、系统安装都放在一条命令里virt-install \ --name centos-dev \ --memory 4096 \ --vcpus 2 \ --disk path/var/lib/libvirt/images/centos-dev.qcow2,size30 \ --os-variant centos-stream9 \ --network networkdefault \ --cdrom /path/to/CentOS-Stream-9.iso参数含义和VBoxManage大同小异分配资源、指定磁盘、接入网络、挂载ISO。理解了一套的原理换工具只是查一下对应参数名。4. 多台虚拟机配合Nginx多站点的网络编排实战单台虚机能跑起来只是第一步。实际开发中我更常遇到的是“本地一台宿主机上跑着好几台虚拟机它们要互相通信还要被宿主机的Nginx统一代理出去实现多站点、自定义域名”这种场景。热搜词里那条“本地虚拟机 多端口nginx 开发环境多站点自定义域名配置”正是这个问题的典型描述。4.1 先选对网络模式NAT、桥接还是host-only多虚机协同第一件事是分清VirtualBox的三种网络模式NAT虚机通过宿主机上网外部访问需端口转发。适合单机上网多机互访麻烦。桥接虚机直接接入物理局域网拥有独立IP。适合让局域网其他设备访问虚机但占用真实IP且在公司网络里容易引发冲突。host-only虚机之间和宿主机组成一个隔离内网虚机不能直接访问外网可以通过宿主机做IP转发实现最适合开发环境。我强烈推荐把开发环境的虚机全部放到host-only网络中再给其中需要上网的机器额外加一张NAT网卡。这样既隔离了和真实局域网的互相干扰又能保证虚机安装软件时有网络。4.2 用host-only把多台虚机放进同一个隔离网段首先检查VirtualBox里有没有host-only网卡没有就创建一张并给它分配网段。比如用192.168.56.0/24# 创建host-only网卡 VBoxManage hostonlyif create # 给网卡配置IP VBoxManage hostonlyif ipconfig vboxnet0 --ip 192.168.56.1 --netmask 255.255.255.0 # 添加DHCP服务可选让虚机自动获取IP VBoxManage dhcpserver add --ifname vboxnet0 --ip 192.168.56.100 \ --netmask 255.255.255.0 --lowerip 192.168.56.101 --upperip 192.168.56.200 --enable然后把每台虚机的第二块网卡设为host-onlyVBoxManage modifyvm web01 --nic2 hostonly --hostonlyadapter2 vboxnet0 VBoxManage modifyvm db01 --nic2 hostonly --hostonlyadapter2 vboxnet0 VBoxManage modifyvm redis01 --nic2 hostonly --hostonlyadapter2 vboxnet0启动全部虚机后它们会各自拿到192.168.56.x的内网IP。宿主机可以直接用ping 192.168.56.101验证连通性。这个拓扑的好处很明显所有虚机之间互通宿主机作为唯一的“外部入口”所有流量都经过你控制的Nginx既安全又好排错。4.3 宿主机Nginx统一入口多站点自定义域名配置现在三台虚机都有了内网IP宿主机要访问它们传统做法是直接填IP加端口比如http://192.168.56.101:8080。但项目多了之后你根本记不住哪台机器哪个端口对应哪个服务。我的做法是用Nginx做一层反向代理通过域名区分项目。先在宿主机hosts文件里做域名映射127.0.0.1 dev-admin.local.com 127.0.0.1 dev-api.local.com 127.0.0.1 dev-static.local.com然后在Nginx配置目录下为每个站点建立一个配置文件核心只有几行server { listen 80; server_name dev-admin.local.com; location / { proxy_pass http://192.168.56.101:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } server { listen 80; server_name dev-api.local.com; location / { proxy_pass http://192.168.56.102:9000; proxy_set_header Host $host; } }浏览器访问dev-admin.local.com请求会先落到宿主机的Nginx再由Nginx转发到对应虚机的对应端口。整个过程对外只暴露80端口域名对应关系文件化之后新增站点只需复制一个server块改三处域名、虚机IP、端口。然后再nginx -s reload一套新的开发环境入口就生效了。这里有个命令行场景下的额外收益虚机和宿主机之间的端口映射、域名映射全部可以写进脚本新环境初始化时一键生成。相比手动在VirtualBox GUI里逐台配置端口转发这种方式可维护性高得多。4.4 为什么坚持用“host-only Nginx”这套组合一是隔离稳定。host-only网络不占用真实局域网IP也不会被公司路由器分配策略影响。虚机IP固定脚本和配置不会时好时坏。二是统一入口。所有服务都从宿主机Nginx进域名管理集中测试环境也好向同事交付给一个域名地址就能访问到对应服务。三是资源可控。桥接模式下虚机直连物理网卡宿主机休眠或切换网络时虚机网络经常跟着掉线host-only配合NAT双网卡则基本没有这个问题。5. 快照、克隆与批量创建让命令行发挥真正价值单台虚机的创建和管理学会后再往前走一步就是批量和状态管理。这也是我从命令行里获得最大收益的地方一套模板机五分钟复制出五台环境一致的全新虚机一个for循环批量打快照批量关机。5.1 快照命令行下一键回滚快照的本质是把虚机的当前状态完整保存下来后续系统搞坏了、配置改乱了一条命令回到快照点。GUI下打快照要右键、选快照、填名称命令行只需要# 给虚机打一个名为clean-state的快照 VBoxManage snapshot centos-dev take clean-state # 查看快照列表 VBoxManage snapshot centos-dev list # 回滚到clean-state VBoxManage snapshot centos-dev restore clean-state # 删除不需要的快照 VBoxManage snapshot centos-dev delete old-snapshot我最常用的工作流是拿到一台新的项目环境后先打一个“初始安装完成”的快照然后在干净状态下搭好开发依赖再打一个“开发环境就绪”的快照。后续无论怎么折腾都能迅速退回到任何一个状态。KVM里对应的virsh snapshot-create-as和virsh snapshot-revert用法基本一样只是命令名不同。5.2 克隆模板机复制与差异化配置比快照更常用的批量场景是克隆。VirtualBox的克隆分两种链接克隆和完整克隆。链接克隆依赖父镜像省空间但父镜像坏了全完蛋完整克隆完全独立稳妥但占磁盘。我通常用完整克隆做模板复制。# 完整克隆并自动注册新虚机 VBoxManage clonevm centos-dev --name web01 --mode machine --register克隆出来的虚机和原机器是完全一样的包括主机名、IP、SSH密钥。因此克隆后必须做的两件事是修改主机名、重置网络配置里的IP或MAC地址以便重新获取IP。这正是命令行封装的价值所在——写一个小脚本克隆完成后自动进入系统把这几项差异化配置改好实现“模板机→批量交付”流水线。5.3 批量创建脚本Shell循环解决一切重复假设项目需要一个由3台Web、1台DB、1台缓存组成的测试集群手工一条条敲命令太笨了。适合的做法是写一个脚本用循环来创建for i in 1 2 3; do VBoxManage clonevm centos-dev --name web0$i --mode machine --register VBoxManage startvm web0$i --type headless done如果连网络配置也要差异化可以把虚机名和期望IP放进一个映射表克隆完成后再用VBoxManage guestcontrol往系统里注入配置脚本。我这里不展开太细核心思想是大多数GUI操作都能映射成一条或多条命令命令排成一行就是脚本脚本攒起来就是自动化运维。5.4 备份恢复命令行导出OVF与定期快照做运维的都知道虚拟机的备份不能只靠“留着vdi文件”。折腾测试环境时我更喜欢用定时任务配合快照来做轻度保护# 每天凌晨3点给重要虚机打快照 0 3 * * * /usr/bin/VBoxManage snapshot centos-dev take auto-daily --description daily backup做真实交付或需要整体迁移时则用OVF导出它会把虚机配置和磁盘打包成一个统一格式拿去哪里都能导入。这个也支持命令行VBoxManage export centos-dev --output centos-dev.ova反之新机器上导入一套现成环境VBoxManage import centos-dev.ova在这里我特别想提醒一件事快照不是越多越好。快照过多会拖慢虚机磁盘性能而且每层快照都是差异存储基盘一旦损坏快照链上的数据恢复难度陡增。合理的做法是“用前打、稳定后删”保留关键节点即可。6. 从常见问题看命令行侧的操作误区与修复命令行工具虽好但踩过的坑一点也不比GUI少甚至有些问题因为在终端下看不到图形反馈排查起来更隐蔽。我挑几个高频问题聊聊它们的根因和命令行修复思路。6.1 VBox虚拟机复制后无法打开UUID冲突这是克隆、迁移VirtualBox虚机时最高发的问题。你复制了一个vdi文件或整个虚机目录双击打开时报错“UUID已经存在”。原因是VirtualBox用UUID标识磁盘文件复制后如果没重新生成UUID两块的标识一样自然就冲突了。命令行修复非常简单# 给vdi生成新的UUID VBoxManage internalcommands sethduuid /path/to/copied.vdi注意执行前先关闭复制出来的虚机修改成功后再次注册虚机问题就解决了。如果我用clonevm克隆而不是手动复制文件VirtualBox会自动处理UUID一般不会遇到这个问题。所以我的排查经验是优先用官方克隆命令手动复制文件时心里要有UUID这回事。6.2 VMware提示“无法连接到虚拟机”服务与权限VMware Workstation用户经常遇到“无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用”这个报错。它出现的原因通常不是虚拟机坏了而是VMware后台服务没启动或者当前用户对.vmx文件没有读写权限。命令行排查思路是先确认服务状态# Windows下检查VMware服务 sc query VMwareAuthorizationService # 如果服务没有运行启动它 net start VMwareAuthorizationService然后检查.vmx目录权限Linux下尤其要注意很多人把虚拟机放在root家目录里普通用户自然没权限。对macOS Fusion用户vmrun报权限错多是未授权终端访问虚拟机需要在Fusion的偏好设置里授权。6.3 虚拟机安装Linux蓝屏虚拟化开关与Hyper-V冲突安装Linux过程中宿主机蓝屏或者虚机根本无法启动是Windows平台常见的翻车现场。排查顺序我一向是三步走先确认BIOS虚拟化是否开启再检查Windows虚拟机监控程序平台和Hyper-V是否关闭最后看VirtualBox/VMware版本是否过老。命令行下检查虚拟化是否开启Windows可以用systeminfo输出里找“Hyper-V 要求”这一段如果显示“虚拟化已启用”基本可以排除BIOS问题。接下来要做的通常是关闭Hyper-V相关功能重新启动后再装虚拟机。这里提醒一句如果你日常还在用Docker Desktop、WSL2这类依赖Hyper-V的工具关掉Hyper-V会影响它们需要权衡取舍。比较稳妥的方案是使用支持与Hyper-V共存的VirtualBox新版本但性能表现一般。6.4 复制粘贴跨越不生效增强工具的安装很多人装完虚拟机后发现在宿主机和虚机之间复制粘贴文本不生效。这个问题的根因不是虚拟机网络而是没有安装Guest AdditionsVirtualBox或VMware Tools。命令行安装其实比GUI省事。以VirtualBox为例先通过光驱挂载增强功能ISOVBoxManage storageattach centos-dev --storagectl SATA --port 1 --device 0 \ --type dvddrive --medium /usr/share/virtualbox/VBoxGuestAdditions.iso然后进入虚机执行安装# 虚机内加载光驱并运行安装脚本 mount /dev/cdrom /mnt /mnt/VBoxLinuxAdditions.run安装完重启虚机剪贴板共享和屏幕分辨率自适应就正常了。这个问题看着小但在命令行工作流里影响其实很大因为很多人远程管理虚机时习惯先在宿主机复制一段命令再粘贴到虚机SSH会话里执行增强工具没装好这个习惯就直接被切断了。一口气写到这其实一个核心体会呼之欲出**不管哪个虚拟化平台命令行工具都不是GUI的替代品那么简单它代表的是“把操作沉淀成命令、把命令沉淀成脚本、把脚本沉淀成规范”的工作方式。**我个人的建议是别贪多先选一套自己最常用的工具把创建、启动、快照、克隆这四个基础操作练到闭眼能写后面你会慢慢发现命令行顺手了之后你更愿意去尝试自动化和批量管理而不会再想回头去点那个图形界面。
返回列表