ARTICLE DETAIL

资讯详情

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

ESXi虚拟机VMRC远程登录:moid获取与URL拼接全攻略

ESXi虚拟机VMRC远程登录:moid获取与URL拼接全攻略 如果你也在管 ESXi 虚拟机大概率遇到过这种场面某台 VM 卡死SSH 连不上网页版 vSphere Client 打开控制台一直转圈而同事双击一个 vmrc:// 开头的链接几秒钟就进到了虚拟机桌面。VMRC 远程登录虚拟机难的不是客户端本身难的是它要求一个叫 moid 的参数。VMRC 的 URL 完全靠 moid 定位虚拟机拿不到 moidVMRC 就是个空壳。这篇文章适合做虚拟化运维、写自动化脚本、或者刚接手别人 ESXi 环境的人。我最早是在一次自动化任务里被迫补上这块知识的需要按虚拟机名字批量生成远程控制台链接结果发现虚拟机名字根本不能用于 VMRC 地址必须把 moid 一个一个挖出来。折腾完之后发现这是 ESXi 管理里很小但绕不过去的技术细节。这篇文章我就把 moid 是什么、怎么获取、怎么用它拼出可用的 VMRC 登录地址以及中间容易踩的坑一次讲清楚。1. moid 到底是什么一次脚本翻车现场带来的认知升级1.1 那次翻车用虚拟机显示名拼 VMRC 地址先说我的实际经历。当时我负责给一组测试环境做远程维护入口需求很简单运维在网页上填一个虚拟机名字后端自动生成 VMRC 链接点开就能连到那台虚拟机。我第一版脚本写得很直接拿虚拟机显示名去拼vmrc://esxi01/?moidwindows-test-01心想名字是唯一的不就行了结果实际跑起来一半连接直接报错“Object not found”另一半连上了但发现连错了机器。后来查资料才明白VMRC 协议里moid参数要求的是虚拟机在 VMware 管理域里的内部编号不是显示名也不是 UUID更不是主机名。显示名可以随便改重名也完全合法用名字去定位虚拟机在 API 层面根本站不住脚。那次之后我就把 moid 当成了 ESXi 运维的基础知识点来补越挖越发现这里面的坑很深因为 VMware 产品线里各种“ID”长得太像了网上教程又经常混着写照抄很容易翻车。1.2 moid 的真实身份管理对象引用不是业务名也不是 UUIDmoid 的全称是 Managed Object ID在 vSphere API 和 SDK 里更常见的叫法是 moref即 Managed Object Reference。它本质上是 vCenter 或 ESXi 管理层用来索引虚拟机的一个内部指针表现形式通常是一串vm-开头的字符串例如vm-1032。打个比方UUID 就像人的身份证号一辈子不变哪怕搬到另一个城市身份证号还是那个而 moid 像物业系统里的门牌号在你这套管理系统里唯一标识某套房但如果搬家换了物业公司门牌号就会重新编。所以在 ESXi/vCenter 体系内moid 是给“管理接口”用的跨 vCenter 做迁移、备份恢复之后虚拟机的 moid 往往就变了但 BIOS UUID 和虚拟机内操作系统看到的硬件信息不会变。这也解释了为什么 VMRC 和 vSphere API 都认 moid 而不认显示名它们本质上都是管理接口需要的是一个稳定的、在管理域内唯一的对象引用。显示名是给人看的moid 是给程序用的。1.3 一组容易混淆的 ID 对照我在实际排查中发现很多人和我一样最先搞混的是下面这几个概念名称举例来源/获取方式能否用于 VMRC显示名 Namewin2019vSphere Client 界面不能BIOS UUID4217 56 8e ...虚拟机 .vmx 文件不能直接使用InstanceUUID5029a....vmx 文件 / API不能直接使用vmid1032vim-cmd vmsvc/getallvms第一列需拼成vm-1032moid / morefvm-1032vSphere 客户端 URL、PowerCLI Id 属性、API可以直接使用World ID51234esxcli vm process list不能那是进程号这里最坑的就是 vmid 和 World ID 的区别。两者都是数字长得差不多但 vmid 是管理对象编号World ID 是 ESXi 内核里的进程 World 编号。VMRC 要的是前者后者纯粹是另一个世界的东西拿 World ID 去拼 VMRC 地址百分之百报“找不到对象”。2. 获取 moid 的四种路径从网页地址栏到命令行到 API2.1 最快路径vSphere Client 地址栏直接捞如果你只是临时需要一两台虚拟机的 moid最快的办法不是敲命令而是直接从浏览器地址栏复制。打开 vSphere Web Client 或 Host Client点击虚拟机图标进入虚拟机详情页这时看地址栏里面通常会带一个类似于vmIdvm-1032或params.vmIdvm-1032的参数vm-1032就是这台虚拟机的 moid。不同版本的 Web Client 参数名可能略有差异有些版本显示的是moidvm-1032有些版本把 vmId 藏在前端路由里但只要是vm-开头的那一串基本就是它。这个方法适合临时应急。缺点也很明显一台一台翻页面太慢而且浏览器地址栏里的参数格式在不同版本之间不统一没法写进自动化脚本里稳定解析。我一般只在排查单台问题、需要快速确认时用它。2.2 ESXi Shell 路径vim-cmd 拿到 Vmid 再拼 moid如果是直接在 ESXi 主机上操作SSH 登录主机后敲vim-cmd vmsvc/getallvms输出大概是这样的Vmid Name File Guest OS Version Annotation 1032 win2019 /vmfs/volumes/ds1/win2019/win2019.vmx windows9Server64Guest vmx-15 1033 ubuntu22 /vmfs/volumes/ds1/ubuntu22/ubuntu22.vmx ubuntu64Guest vmx-15第一列Vmid就是这台虚拟机在这个 ESXi 管理域里的对象编号。注意它输出的是纯数字VMRC URL 里要的是vm-1032这种带前缀的格式所以用的时候需要手动拼一个vm-前缀。为什么vim-cmd的 vmid 能对上 moid因为 vim-cmd 走的是 VMware OM (VMOMI) 接口和 vSphere API 是同一条链路它查出来的就是管理对象层的信息。而esxcli走的是另一套系统工具链返回的东西口吻完全不一样。2.3 esxcli 的 World ID 为什么不行网上搜“ESXi 获取虚拟机ID”很大概率会搜到这条命令esxcli vm process list输出大概是这样的win2019 World ID: 51234 Process ID: 0 VMX Cartel ID: 51233 ...这里的World ID是 ESXi 内核里这个虚拟机的运行进程编号。在 ESXi 的世界模型里每一个运行中的进程叫一个 World虚拟机由一组 World 组成World ID 是内核用来调度和定位进程用的。为什么很多人会误用因为输出里有 VM 名字有数字 ID想当然地就填到 moid 参数里了。最关键的是VMRC 连接的时候它要找的是管理对象层的东西而不是内核进程层的东西。World ID 可能在虚拟机重启之后就变了甚至某些状态下压根查不到用它去定位虚拟机完全不可靠。所以记住esxcli vm process list 这两位数字只能用来做进程级的排查比如定位卡死的 VM 然后 kill千万不能拿来拼 VMRC 地址。2.4 编程式获取PowerCLI、pyVmomi、govc要批量、要自动化就得用编程方式拿 moid。最常用的三套工具PowerCLI 里虚拟机的Id属性返回的是VirtualMachine-vm-1032这种格式中间的vm-1032就是 moidGet-VM -Name win2019 | Select-Object Name, Id输出Name Id ---- -- win2019 VirtualMachine-vm-1032Python 使用 pyVmomi 时遍历出来的虚拟机对象有一个_moId属性from pyVmomi import vim from pyVim.connect import SmartConnect, Disconnect si SmartConnect(hostvc01, useradministratorvsphere.local, pwdsecret) content si.RetrieveContent() for datacenter in content.rootFolder.childEntity: for vm in datacenter.vmFolder.childEntity: if isinstance(vm, vim.VirtualMachine): print(vm.name, vm._moId)govc 命令行工具也有捷径比如govc ls -l会在输出里带上对象的 moid 标识。编程方式的价值在于moid 拿到后可以直接拼成 VMRC 链接、喂给工单系统、或者存到 CMDB 里整个过程可重复执行不会因为 UI 版本变化而失效。3. VMRC 登录实操URL 格式、客户端安装和两种环境差异3.1 VMRC 比网页 Console 强在哪VMRC 全称 VMware Remote Console是 VMware 官方提供的独立远程控制台客户端。很多人平时都用网页版 Console觉得没必要装客户端直到虚拟机出现网络栈故障、系统蓝屏、或者 VM 卡在 BIOS 阶段时才意识到网页控制台这时往往是最难用的。实测下来VMRC 的优势主要在几个场景虚拟机没有网卡驱动或系统彻底崩溃时VMRC 直接走虚拟硬件的控制台通道能进入 BIOS/PXE 界面网页 Console 受浏览器和网络协议限制较多长时间滚动日志、安装系统这种高频画面刷新场景VMRC 渲染更稳网页版明显延迟VMRC 支持 USB 设备重定向、多显示器、Unity 模式这些是网页版没有的可以脱离浏览器用vmrc://协议直接在命令行唤起方便脚本和工单系统集成。所以我的习惯是日常快速看一眼用网页 Console一旦需要认真操作、故障修复、系统安装一律切 VMRC。3.2 vmrc:// URL 从 moid 到连接的全部拆解VMRC 的 URL 格式其实非常简单vmrc://主机地址/?moidvm-1032带账号密码时vmrc://用户名:密码主机地址/?moidvm-1032主机地址可以是 vCenter 的地址也可以是独立 ESXi 的地址取决于你的虚拟机挂在谁下面管理。端口默认走 443如果改了 Web 服务端口可以在主机地址后面加冒号端口。这里有一个特别容易踩的细节如果用户名或密码里带有、:、/、?、#这类特殊字符必须先做 URL 编码再拼到链接里。比如 SSO 账号administratorvsphere.local里面的要写成%40vmrc://administrator%40vsphere.local:P%40ssw0rdvc01/?moidvm-1032我见过很多人折腾了半天认证失败最后发现只是密码里的没编码URL 解析器把后半段当成了主机地址。这种错误很难一眼看出来建议在脚本里用encodeURIComponent或urllib.parse.quote自动生成而不是手写。另外部分旧教程会提到dcPath参数说是要指定数据中心路径。那是老版本 VMRC 才需要的兼容参数现在主流的 VMRC 9/10/12 系列基本靠 moid 就能定位别再被旧教程带偏。3.3 各平台安装与唤起方式VMRC 客户端 Windows、Linux、macOS 都有官方安装包安装完成后会自动注册vmrc://协议关联。Windows 下安装完命令行直接这样用C:\Program Files (x86)\VMware\VMware Remote Console\vmrc.exe vmrc://administrator%40vsphere.local:P%40ssw0rdvc01/?moidvm-1032不想敲全路径可以直接用Start-Process vmrc://administrator%40vsphere.local:P%40ssw0rdvc01/?moidvm-1032在浏览器地址栏输入同样的链接Chrome 会弹“是否允许打开外部协议”确认后也会唤起 VMRC 客户端。macOS 和 Linux 的原理一样安装对应的 VMRC 包后在终端里执行类似命令就能唤起客户端。Linux 下路径通常是/usr/bin/vmrc不同发行版略有区别。3.4 ESXi 与 vCenter 环境各自的正确用法这里的核心原则是你的 VMRC URL 指向哪个管理端moid就必须是那个管理端认识的 moid。独立 ESXi 主机场景主机地址填 ESXi IPmoid 用这台 ESXi 上vim-cmd vmsvc/getallvms拿到的 vmid 拼vm-前缀账号填 ESXi 的本地账号通常是 root。vCenter 托管场景主机地址填 vCenter IP 或域名moid 必须用 vCenter 里查询到的 moid不能直接拿底层 ESXi 的 vmid 来用账号填 vCenter 用户SSO 域用户如administratorvsphere.local。这条规则我认为是整个 VMRC 使用里最重要的一条。很多人先 SSH 到 ESXi 上跑vim-cmd拿到了 vmid然后把它填到指向 vCenter 的 VMRC 地址里结果怎么连都连不上原因就是 vCenter 和 ESXi 各自维护了一套 moref 命名空间同名编号可能指向完全不同的对象。4. 批量自动化PowerCLI 从 vCenter 导出 moid 并拼接 VMRC 链接4.1 一键导出全量虚拟机 moid 清单实际工作中几百台虚拟机的环境靠一台一台翻页面根本不现实必须批量导出。PowerCLI 是最顺手的工具。连接 vCenter 后执行Connect-VIServer vc01.company.local Get-VM | ForEach-Object { $moid [regex]::Match($_.Id, vm-\d).Value [PSCustomObject]{ Name $_.Name Moid $moid } } | Export-Csv -Path vm-moid-list.csv -NoTypeInformation这里用正则提取vm-数字而不是简单 split是因为有些环境的虚拟机对象 ID 格式可能略有差异正则匹配更稳。导出后 CSV 里就是一份“虚拟机名 - moid”的对照表后续不管是拼 VMRC 链接还是调用其他 API直接查表就行。4.2 把 moid 翻译成可直接分发的 VMRC URL拿到 moid 后拼 VMRC URL 就是字符串拼接的活了。我习惯直接在导出时就把 URL 一起生成$vc vc01.company.local $user administrator%40vsphere.local Get-VM | ForEach-Object { $moid [regex]::Match($_.Id, vm-\d).Value $url vmrc://$user$vc/?moid$moid [PSCustomObject]{ Name $_.Name Moid $moid VMRCUrl $url } } | Export-Csv -Path vm-vmrc-links.csv -NoTypeInformation生成的 CSV 可以直接分发给运维同事他们只需要把VMRCUrl复制进浏览器或命令行就能打开对应虚拟机。如果你希望对方少输入一次密码可以把密码也编码进 URL但这有安全风险。我一般不把明文密码写进文件而是让使用者手动输入或者用系统级凭据服务保存。生产环境里 URL 一旦进了日志、聊天记录、工单系统密码泄露的风险就控制不住了这个取舍一定要想清楚。4.3 Python 方向的 moid 获取示例如果你们运维栈以 Python 为主pyVmomi 也能做到类似效果。核心代码块在拿到虚拟机对象后_moId就是 moidfrom pyVmomi import vim from pyVim.connect import SmartConnect, Disconnect si SmartConnect( hostvc01.company.local, useradministratorvsphere.local, pwdyour-password, disable_ssl_verificationTrue ) content si.RetrieveContent() vm_map {} for datacenter in content.rootFolder.childEntity: for vm in datacenter.vmFolder.childEntity: if isinstance(vm, vim.VirtualMachine): vm_map[vm.name] vm._moId for name, moId in vm_map.items(): print(f{name}: {moId}) Disconnect(si)拿到 moid 后拼链接的方式和 PowerShell 方向完全一致。这套思路甚至可以接到内部 CMDB 或自动化平台里虚拟机创建后自动登记 moid需要远程维护时直接从数据库里取 moid 拼链接比每次现查要快得多。5. 线上踩坑记录VMRC 连接失败的排查链路与经验5.1 案例一把 World ID 当 moidVMRC 找不到虚拟机现象深夜接到告警一台测试虚机卡死同事发来一段命令输出的截图里面明显有World ID: 51234他把moid51234写进 VMRC URL客户端弹出“无法解析虚拟机引用”的报错。排查过程我第一反应是检查 URL 格式发现moid51234只有数字没有vm-前缀以为只是漏了前缀。加上vm-变成moidvm-51234后还是报同样错误。接着排查账号权限确认账号能正常登录 vSphere排除了权限因素。最后才意识到这个 51234 根本不是vim-cmd vmsvc/getallvms出来的 vmid而是esxcli vm process list出来的 World ID。根因确认World ID 属于内核进程域与管理对象域完全隔离VMRC 和 vSphere API 都不认它。正确做法SSH 登录 ESXi执行vim-cmd vmsvc/getallvms拿第一列 vmid 拼成vm-1032这种格式再填 URL。这条案例我特意放在第一个因为它的错误信息很迷惑看起来像是 URL 格式问题实际是数据来源选错了。以后看到 VMRC 报“对象不存在”先不要盯着 URL 格式排查先确认手头的数字到底是哪一路 ID。5.2 案例二密码特殊字符未 URL 编码陷入认证死循环现象VMRC 启动后弹出认证窗口输入密码后又弹回来来回几次后直接报“身份验证失败”。但同样一组账号密码打开浏览器访问 vSphere Web Client 却一切正常。排查过程一开始我也以为是账号密码真的错了反复找管理员确认。后来我把 URL 打出来一行一行检查才发现密码里有个字符直接写进 URL 后VMRC 把密码从处截断了后面的内容被当成了主机地址。整个 URL 的解析自然全乱套。根因确认URL 里特殊字符未转义导致协议解析器无法正确区分用户信息、主机地址和路径参数。正确做法对用户名、密码分别做 URL 编码。手工替换也可以Python 里这样处理import urllib.parse username administratorvsphere.local password Pss:w0rd/ enc_user urllib.parse.quote(username, safe) enc_pwd urllib.parse.quote(password, safe) url fvmrc://{enc_user}:{enc_pwd}vc01/?moidvm-1032 print(url)PowerShell 里可以用[uri]::EscapeDataString()效果一样。这条经验后来被我写进了自动化脚本模板只要涉及 URL 拼接一律先编码再拼宁可编码两次也不能漏一次。5.3 案例三浏览器无法唤起 vmrc:// 协议现象点击某个网页里生成的vmrc://链接Chrome 没任何反应也没有弹外部协议确认框换 Edge 也一样。排查过程先确认本机装了 VMRC 客户端并且能从开始菜单正常打开。然后在注册表里检查HKEY_CLASSES_ROOT\vmrc是否关联到了 vmrc.exe发现关联项存在但命令路径指向了已经卸载的旧版本目录。原因是公司合规要求之前所有机器统一卸载了老版 VMRC后来又装了一个新版本但安装位置变了协议关联没自动更新。另外还有一种可能是浏览器策略禁用了外部协议唤起。正确做法优先使用命令行方式绕过浏览器直接执行 vmrc.exe。Windows 下Start-Process -FilePath C:\Program Files (x86)\VMware\VMware Remote Console\vmrc.exe -ArgumentList vmrc://vc01/?moidvm-1032如果确实需要浏览器唤起可以手动修复注册表把HKEY_CLASSES_ROOT\vmrc\shell\open\command的默认值指向新版本的 vmrc.exe。域环境里建议把 VMRC 安装和协议关联做成标准软件包下发省得每人手工折腾。5.4 案例四vCenter 环境混用 ESXi 的 vmid现象vCenter 管理着两台 ESXi同事 SSH 到其中一台 ESXi 上执行vim-cmd vmsvc/getallvms拿到了 vmid 12然后在 VMRC 链接里填vmrc://vc01/?moidvm-12VMRC 报错“无法找到虚拟机”。排查过程单独看 vmid 12 在 ESXi 上是存在的指向一台 Windows 虚拟机但在 vCenter 的命名空间里根本没有vm-12这个对象。vCenter 的 moid 是按它的全局顺序分配的我对同一台虚拟机的 vCenter moid 是vm-2048而 ESXi 本地 vmid 是 12。根因确认ESXi 与 vCenter 各自维护独立的 moref 命名空间互相不能混用。VMRC 链接指向哪个管理端就要填哪个管理端认识的 moid。正确做法在 vCenter 场景下统一通过 PowerCLI 或 pyVmomi 连接 vCenter 获取 moid不要再从底层 ESXi 去拿。这也是我前面说“编程式获取”更适合自动化环境的原因——它能保证拿到的 moid 和 VMRC URL 里的管理端是对应的。我把这次排查过程完整记下来就是因为“moid 拿错”这个错误太容易复现了。现在每次接手一套新环境我都会先跑一遍vim-cmd vmsvc/getallvms把 ESXi 层面的 vmid 摸清楚再通过 PowerCLI 导一份 vCenter 的 moid 清单对照着放进运维文档。这套动作已经变成我进入新环境的固定套路后面做 VMRC 远程登录和自动化脚本时基本不会再出幺蛾子。希望这篇也能帮你少走几趟弯路。
返回列表