戰(zhàn):qt-virt-manager編譯配置與虛擬機(jī)管理指南)
簡(jiǎn)介qt-virt-manager 是一款基于 Qt 框架開(kāi)發(fā)的跨平臺(tái)圖形化虛擬機(jī)管理工具面向系統(tǒng)管理員、運(yùn)維工程師及虛擬化技術(shù)學(xué)習(xí)者旨在用統(tǒng)一界面屏蔽 VMware、LXC、BHYVE、Libvirt、Hyper-V、OpenVZ、QEMU-KVM、VirtualBox 等多種虛擬化技術(shù)的差異降低多平臺(tái)管理成本。資源以 zip 壓縮包形式提供包體約 3.08MB上游未提供文件總數(shù)與類型明細(xì)可視為輕量級(jí)源碼或工程歸檔便于快速獲取與本地部署。目前已有 345 人瀏覽學(xué)習(xí)屬于小眾但垂直的實(shí)用工具類資源。其價(jià)值在于一方面通過(guò) QtC 構(gòu)建現(xiàn)代美觀的 GUI保證不同桌面環(huán)境下體驗(yàn)一致另一方面圍繞虛擬機(jī)創(chuàng)建、啟停、資源分配、網(wǎng)絡(luò)配置、克隆備份與遷移等操作提供統(tǒng)一入口并可與 virt-viewer 配合完成遠(yuǎn)程圖形會(huì)話。對(duì)于需要同時(shí)接觸容器與全虛擬化、希望用一套工具串聯(lián) Libvirt 與 QEMU-KVM 等后端的讀者可作為理解虛擬化管理抽象層的參考實(shí)現(xiàn)。1. 從 qt-virt-manager 說(shuō)起一個(gè)被低估的 Qt 虛擬機(jī)管理前端如果你在 Linux 桌面環(huán)境下同時(shí)跑著 KVM、QEMU、LXC 甚至遠(yuǎn)程 libvirt 節(jié)點(diǎn)大概率經(jīng)歷過(guò)這種場(chǎng)景想快速看一眼某臺(tái)虛擬機(jī)的內(nèi)存占用、臨時(shí)掛一塊磁盤、改一下 vCPU 數(shù)量結(jié)果要么打開(kāi) virt-manager 等它慢慢刷新要么直接 ssh 上去敲virsh命令。qt-virt-manager 就是沖著這個(gè)痛點(diǎn)來(lái)的——它是一個(gè)基于 Qt 的 libvirt 圖形化管理前端用 C/Qt 寫(xiě)成直接對(duì)接 libvirt API把本地和遠(yuǎn)程的虛擬機(jī)、存儲(chǔ)池、網(wǎng)絡(luò)、卷這些對(duì)象用一套桌面界面管起來(lái)。它和 virt-manager 的定位不同virt-manager 是 Python/GTK 的“全能選手”而 qt-virt-manager 更輕、更貼近 Qt 技術(shù)棧適合那些本來(lái)就在做 Qt 開(kāi)發(fā)、想順手把虛擬機(jī)管理嵌進(jìn)自己工具鏈的人。這篇文章不講空泛概念而是把 qt-virt-manager 這類 Qt libvirt 方案從環(huán)境搭建、編譯、連接、日常操作到踩坑排查整條鏈路講透新手能照著跑通熟手能看到參數(shù)邊界和取舍理由。2. 環(huán)境準(zhǔn)備與依賴把 libvirt、Qt 和編譯鏈一次裝對(duì)2.1 為什么選 Qt libvirt 而不是直接調(diào) virsh很多人第一反應(yīng)是“我寫(xiě)個(gè) shell 腳本包一層 virsh 不就行了”。短期看確實(shí)快但一旦你要做實(shí)時(shí)刷新、事件監(jiān)聽(tīng)、多連接并發(fā)、圖形化展示磁盤/網(wǎng)絡(luò)拓?fù)鋝hell 就會(huì)迅速失控。libvirt 提供的是 C API有完整的事件循環(huán)、異步回調(diào)、錯(cuò)誤碼體系Qt 提供的是信號(hào)槽、模型視圖、跨平臺(tái)窗口系統(tǒng)。qt-virt-manager 這類項(xiàng)目的核心價(jià)值就是把 libvirt 的virConnectPtr、virDomainPtr這些裸指針?lè)庋b成 Qt 對(duì)象讓domainStarted、domainStopped這類事件直接變成信號(hào)UI 層只負(fù)責(zé)連槽函數(shù)。從選型上說(shuō)如果你只是偶爾開(kāi)關(guān)機(jī)virsh足夠如果你要做的是一個(gè)長(zhǎng)期維護(hù)的桌面工具或者要把虛擬機(jī)管理能力嵌進(jìn)已有的 Qt 應(yīng)用那 Qt libvirt 是更穩(wěn)的路線。常見(jiàn)做法是用libvirt-dev拿到頭文件和鏈接庫(kù)用 Qt 的QProcess或直接QLibrary加載 libvirt再自己寫(xiě)一層薄封裝。qt-virt-manager 本身已經(jīng)把這層封裝做完了所以更實(shí)際的做法是直接編譯它、跑起來(lái)、再按需改。2.2 依賴清單與安裝命令在 Ubuntu/Debian 系上把編譯 qt-virt-manager 所需的東西一次裝齊。下面這套命令我在 Ubuntu 22.04 和 24.04 上都跑過(guò)Qt5 和 Qt6 的差異后面單獨(dú)說(shuō)。# 基礎(chǔ)編譯工具 sudo apt update sudo apt install -y build-essential cmake git pkg-config # libvirt 開(kāi)發(fā)庫(kù)和守護(hù)進(jìn)程 sudo apt install -y libvirt-dev libvirt-daemon-system libvirt-clients # Qt5 核心組件qt-virt-manager 多數(shù)分支基于 Qt5 sudo apt install -y qtbase5-dev qttools5-dev qttools5-dev-tools sudo apt install -y libqt5svg5-dev libqt5xmlpatterns5-dev # 可選如果你要用 Qt6 編譯換成下面這組 # sudo apt install -y qt6-base-dev qt6-tools-dev qt6-tools-dev-tools裝完后先確認(rèn) libvirt 守護(hù)進(jìn)程在跑并且當(dāng)前用戶有權(quán)限連上默認(rèn)的qemu:///systemsudo systemctl enable --now libvirtd sudo systemctl status libvirtd --no-pager # 把當(dāng)前用戶加入 libvirt 組避免每次都要 sudo sudo usermod -aG libvirt $USER sudo usermod -aG kvm $USER # 重新登錄后驗(yàn)證 virsh -c qemu:///system list --all這里有個(gè)關(guān)鍵點(diǎn)qemu:///system和qemu:///session是兩套完全不同的連接。/system走的是系統(tǒng)級(jí) libvirtd能管理所有虛擬機(jī)但需要權(quán)限/session是當(dāng)前用戶會(huì)話級(jí)權(quán)限寬松但功能受限網(wǎng)絡(luò)和存儲(chǔ)池支持都不完整。qt-virt-manager 默認(rèn)一般連/system所以組權(quán)限必須配對(duì)否則界面能打開(kāi)但列表是空的這個(gè)坑后面還會(huì)細(xì)說(shuō)。2.3 獲取源碼與目錄結(jié)構(gòu)預(yù)判qt-virt-manager 的源碼通常托管在公開(kāi)的代碼托管平臺(tái)上常見(jiàn)做法是直接 clone 主分支。由于不同分支的構(gòu)建系統(tǒng)可能是 qmake 或 cmake拿到源碼后先看根目錄有沒(méi)有CMakeLists.txt或.pro文件這決定了你下一步用哪套命令。git clone qt-virt-manager 倉(cāng)庫(kù)地址 qt-virt-manager cd qt-virt-manager # 先看構(gòu)建系統(tǒng) ls -la | grep -E CMakeLists.txt|\.pro$ # 如果是 cmake mkdir -p build cd build cmake .. -DCMAKE_BUILD_TYPERelease make -j$(nproc) # 如果是 qmake qmake qt-virt-manager.pro make -j$(nproc)參數(shù)說(shuō)明-DCMAKE_BUILD_TYPERelease關(guān)掉調(diào)試符號(hào)、開(kāi)優(yōu)化日常用足夠如果你要改代碼調(diào)試換成Debug并加-DCMAKE_EXPORT_COMPILE_COMMANDSON方便 clangd 或 vscode 做補(bǔ)全。-j$(nproc)用滿 CPU 核數(shù)編譯大型 Qt 項(xiàng)目時(shí)能省不少時(shí)間。如果編譯中途報(bào)cannot find -lpublic這類鏈接錯(cuò)誤八成是某個(gè)子模塊沒(méi)編出來(lái)或者庫(kù)路徑?jīng)]配對(duì)先看make輸出里第一個(gè) error不要被后面一堆連鎖報(bào)錯(cuò)帶偏。3. 編譯與首次運(yùn)行從 cmake 到能連上 qemu:///system3.1 編譯期最常見(jiàn)的三類報(bào)錯(cuò)與處理第一類是 Qt 模塊缺失典型報(bào)錯(cuò)是error: unknown module(s) in qt: webenginewidgets或者找不到QtSvg。這說(shuō)明你裝的qtbase5-dev不夠缺了對(duì)應(yīng)的子模塊包。解決辦法是按報(bào)錯(cuò)里的模塊名去裝libqt5xxx5-dev比如webenginewidgets對(duì)應(yīng)qtwebengine5-devsvg對(duì)應(yīng)libqt5svg5-dev。第二類是 libvirt 頭文件找不到報(bào)fatal error: libvirt/libvirt.h: No such file or directory。這通常是libvirt-dev沒(méi)裝或者 pkg-config 路徑不對(duì)。用pkg-config --cflags --libs libvirt驗(yàn)證一下如果輸出為空說(shuō)明.pc文件不在默認(rèn)搜索路徑需要手動(dòng)指定PKG_CONFIG_PATH。第三類是 moc/uic 相關(guān)錯(cuò)誤比如undefined reference to vtable for Xxx。這幾乎都是因?yàn)槟硞€(gè)帶Q_OBJECT宏的類沒(méi)有被 moc 處理常見(jiàn)于你手動(dòng)新增了文件但沒(méi)加進(jìn).pro或CMakeLists.txt。檢查構(gòu)建腳本里的SOURCES/HEADERS列表確保新文件都在。# 驗(yàn)證 libvirt 開(kāi)發(fā)環(huán)境是否就緒 pkg-config --modversion libvirt pkg-config --cflags --libs libvirt # 如果輸出正常類似 # 10.0.0 # -I/usr/include/libvirt -lvirt -lvirt-qemu3.2 首次連接 libvirt 與界面初始化編譯成功后直接運(yùn)行生成的二進(jìn)制。第一次啟動(dòng)時(shí)qt-virt-manager 會(huì)嘗試連接默認(rèn)的 libvirt URI。如果界面打開(kāi)后左側(cè)連接列表是空的或者彈出“無(wú)法連接到 hypervisor”的提示按下面順序排查。# 1. 確認(rèn) libvirtd 在跑 systemctl is-active libvirtd # 2. 確認(rèn)當(dāng)前用戶能直接連 virsh -c qemu:///system list --all # 3. 如果 virsh 報(bào)權(quán)限錯(cuò)誤檢查組 id | grep -E libvirt|kvm # 4. 如果組已加但沒(méi)生效重新登錄或臨時(shí)用 sg sg libvirt -c virsh -c qemu:///system list --all連接成功后界面一般會(huì)分成幾個(gè)區(qū)域左側(cè)是連接和虛擬機(jī)樹(shù)中間是虛擬機(jī)詳情狀態(tài)、CPU、內(nèi)存、磁盤、網(wǎng)卡右側(cè)或底部是控制臺(tái)。qt-virt-manager 的控制臺(tái)通常走 VNC 或 SPICE這取決于虛擬機(jī) XML 里graphics節(jié)點(diǎn)的配置。如果控制臺(tái)黑屏先確認(rèn)虛擬機(jī)的graphics typevnc .../端口有沒(méi)有被防火墻擋住以及virt-viewer或spice-client-gtk是否裝了。3.3 用 Qt 信號(hào)槽理解事件刷新機(jī)制qt-virt-manager 能做到“虛擬機(jī)一關(guān)機(jī)界面就變灰”靠的是 libvirt 的事件回調(diào)。libvirt 提供virConnectDomainEventRegisterAny可以注冊(cè)對(duì)域生命周期事件的監(jiān)聽(tīng)。Qt 封裝層通常會(huì)在一個(gè)獨(dú)立線程里跑virEventRunDefaultImpl收到事件后通過(guò)QMetaObject::invokeMethod或自定義信號(hào)把消息拋回主線程更新 UI。如果你要自己擴(kuò)展功能比如加一個(gè)“虛擬機(jī) CPU 使用率實(shí)時(shí)曲線”思路是在連接對(duì)象里注冊(cè)virConnectDomainEventRegisterAny監(jiān)聽(tīng)狀態(tài)變化同時(shí)用QTimer定時(shí)調(diào)virDomainGetInfo拿 CPU 時(shí)間再換算成百分比。注意 libvirt 的 CPU 時(shí)間是累計(jì)值要兩次采樣做差再除以時(shí)間間隔直接讀單次值是沒(méi)有意義的。// 偽代碼示意定時(shí)采樣虛擬機(jī) CPU 使用率 // 關(guān)鍵點(diǎn)virDomainGetInfo 返回的 cpuTime 是累計(jì)納秒需要差分 virDomainInfo info; if (virDomainGetInfo(domain, info) 0) { unsigned long long now info.cpuTime; if (lastCpuTime 0) { double delta (now - lastCpuTime) / 1e9; // 秒 double usage delta / intervalSec / vcpuCount * 100.0; emit cpuUsageChanged(usage); } lastCpuTime now; }參數(shù)說(shuō)明info.cpuTime單位是納秒vcpuCount是虛擬機(jī)當(dāng)前分配的 vCPU 數(shù)intervalSec是定時(shí)器間隔。這個(gè)算法在虛擬機(jī)空閑時(shí)會(huì)有小幅抖動(dòng)屬于正?,F(xiàn)象不要用單次采樣去判斷“虛擬機(jī)是不是卡了”。4. 日常操作與參數(shù)調(diào)優(yōu)存儲(chǔ)池、網(wǎng)絡(luò)和快照怎么配4.1 存儲(chǔ)池與卷的創(chuàng)建路徑和權(quán)限是重災(zāi)區(qū)qt-virt-manager 里創(chuàng)建虛擬機(jī)前通常要先有存儲(chǔ)池。存儲(chǔ)池分幾種類型dir目錄型最簡(jiǎn)單、logicalLVM、netfs網(wǎng)絡(luò)文件系統(tǒng)、iscsi等。新手建議從dir開(kāi)始路徑選一個(gè)磁盤空間充足、權(quán)限明確的位置比如/var/lib/libvirt/images或你自己掛載的數(shù)據(jù)盤。# 用 virsh 先建一個(gè)目錄型存儲(chǔ)池qt-virt-manager 界面里操作等價(jià) mkdir -p /data/vm-pool virsh pool-define-as vm-pool dir --target /data/vm-pool virsh pool-build vm-pool virsh pool-start vm-pool virsh pool-autostart vm-pool # 驗(yàn)證 virsh pool-list --all virsh vol-list vm-pool關(guān)鍵參數(shù)--target是池的根目錄必須存在且 libvirt 進(jìn)程有讀寫(xiě)權(quán)限。如果你把池放在/root或某個(gè)只有 root 能進(jìn)的目錄qemu:///system下的 qemu 進(jìn)程會(huì)以libvirt-qemu用戶身份去讀權(quán)限不夠就會(huì)報(bào)“Permission denied”。解決辦法是chown -R libvirt-qemu:kvm /data/vm-pool或者把目錄權(quán)限設(shè)成0775并確保組對(duì)。這個(gè)坑在“虛擬機(jī)安裝 linux 藍(lán)屏”這類搜索里經(jīng)常被誤判成鏡像問(wèn)題其實(shí)很多時(shí)候是存儲(chǔ)池權(quán)限沒(méi)配對(duì)。4.2 網(wǎng)絡(luò)配置默認(rèn) NAT 和橋接的取舍libvirt 默認(rèn)會(huì)創(chuàng)建一個(gè)default網(wǎng)絡(luò)走 NAT虛擬機(jī)可以上網(wǎng)但外部訪問(wèn)虛擬機(jī)需要端口轉(zhuǎn)發(fā)。如果你要做服務(wù)器類虛擬機(jī)需要外部直接訪問(wèn)那就得配橋接。qt-virt-manager 的網(wǎng)絡(luò)管理界面能創(chuàng)建和編輯這些網(wǎng)絡(luò)但底層還是寫(xiě) XML。!-- 默認(rèn) NAT 網(wǎng)絡(luò)的核心配置 -- network namedefault/name forward modenat/ bridge namevirbr0 stpon delay0/ ip address192.168.122.1 netmask255.255.255.0 dhcp range start192.168.122.2 end192.168.122.254/ /dhcp /ip /network橋接網(wǎng)絡(luò)則需要宿主機(jī)上先有一個(gè)橋接口比如br0然后把物理網(wǎng)卡掛上去。這一步在不同發(fā)行版上差異很大NetworkManager 和 systemd-networkd 的配置方式完全不同。常見(jiàn)做法是先用發(fā)行版工具把橋建好確認(rèn)宿主機(jī)自己能通過(guò)橋上網(wǎng)再在 libvirt 里定義forward modebridge/并指定bridge namebr0/。順序反了會(huì)出現(xiàn)“虛擬機(jī)拿不到 IP 但宿主機(jī)正?!钡男W(xué)現(xiàn)象。4.3 快照與磁盤格式qcow2 的邊界qt-virt-manager 支持對(duì)虛擬機(jī)做快照但快照能不能用、好不好用取決于磁盤格式。qcow2支持內(nèi)部快照和外部快照raw格式不支持快照。如果你建虛擬機(jī)時(shí)選了 raw后面想加快照就得先轉(zhuǎn)換格式而轉(zhuǎn)換又需要停機(jī)這就是典型的“當(dāng)初圖快后面后悔”。# 查看虛擬機(jī)磁盤格式 virsh domblklist vm-name qemu-img info /data/vm-pool/disk.qcow2 # 創(chuàng)建內(nèi)部快照虛擬機(jī)可以運(yùn)行中做但建議停機(jī)做更穩(wěn) virsh snapshot-create-as vm-name snap1 before upgrade # 查看快照列表 virsh snapshot-list vm-name # 回滾 virsh snapshot-revert vm-name snap1參數(shù)說(shuō)明內(nèi)部快照把狀態(tài)存在 qcow2 文件內(nèi)部管理簡(jiǎn)單但性能會(huì)隨快照數(shù)量增加而下降外部快照把增量寫(xiě)到單獨(dú)文件性能更好但管理復(fù)雜需要自己維護(hù) backing chain。日常用內(nèi)部快照做“升級(jí)前保底”足夠但不要長(zhǎng)期堆幾十個(gè)快照不合并否則qemu-img info會(huì)看到一串 backing file讀寫(xiě)放大很嚴(yán)重。5. 避坑與排查qt-virt-manager 使用中的五類真實(shí)翻車5.1 界面能打開(kāi)但虛擬機(jī)列表為空現(xiàn)象qt-virt-manager 啟動(dòng)正常左側(cè)連接節(jié)點(diǎn)也在但展開(kāi)后沒(méi)有任何虛擬機(jī)而virsh list --all明明能看到。原因最常見(jiàn)的是連接 URI 不一致。qt-virt-manager 默認(rèn)可能連的是qemu:///session而你的虛擬機(jī)建在qemu:///system下。另一個(gè)原因是當(dāng)前用戶不在libvirt組libvirt 對(duì)無(wú)權(quán)限用戶返回的是空列表而不是報(bào)錯(cuò)所以界面看起來(lái)“正?!?。解決在 qt-virt-manager 的連接設(shè)置里顯式把 URI 改成qemu:///system然后確認(rèn)id輸出里有l(wèi)ibvirt組。如果剛加完組必須重新登錄一次newgrp libvirt只對(duì)當(dāng)前 shell 有效圖形程序不一定繼承。5.2 控制臺(tái)黑屏或提示找不到 platform plugin現(xiàn)象虛擬機(jī)詳情能看但點(diǎn)“控制臺(tái)”后窗口一片黑或者終端里報(bào)qt.qpa.plugin: could not find the Qt platform plugin linuxfb。原因前半句黑屏通常是 VNC/SPICE 端口沒(méi)通或者graphics配置不對(duì)后半句是 Qt 運(yùn)行環(huán)境問(wèn)題linuxfb是嵌入式平臺(tái)插件桌面環(huán)境不該用它。出現(xiàn)這個(gè)報(bào)錯(cuò)說(shuō)明QT_QPA_PLATFORM被設(shè)成了linuxfb或者 Qt 插件路徑被污染。解決先unset QT_QPA_PLATFORM再檢查QT_PLUGIN_PATH有沒(méi)有指向奇怪的目錄。如果是交叉編譯到樹(shù)莓派這類場(chǎng)景l(fā)inuxfb才是對(duì)的但桌面端必須用xcb或wayland。控制臺(tái)黑屏則用virsh domdisplay vm-name看實(shí)際端口再用telnet或nc測(cè)一下通不通。5.3 編譯時(shí)報(bào) cannot mix incompatible Qt library現(xiàn)象編譯或運(yùn)行時(shí)報(bào)fatal: cannot mix incompatible Qt library (version ex50601) with this library。原因系統(tǒng)里同時(shí)存在多個(gè) Qt 版本比如 Qt5 和 Qt6或者你自己編譯的 Qt 和 apt 裝的 Qt 混用。ex50601這種版本號(hào)說(shuō)明鏈接時(shí)找到的庫(kù)和頭文件版本不一致。解決用ldd看二進(jìn)制實(shí)際鏈接的 Qt 庫(kù)路徑用qmake -query看當(dāng)前 qmake 指向的 Qt 安裝前綴。最干凈的做法是在 cmake 里顯式指定-DCMAKE_PREFIX_PATH/usr/lib/x86_64-linux-gnu/cmake/Qt5強(qiáng)制用系統(tǒng) Qt5。如果之前裝過(guò)多個(gè) Qt把不需要的從PATH和LD_LIBRARY_PATH里清掉。5.4 虛擬機(jī)啟動(dòng)報(bào)權(quán)限錯(cuò)誤但 virsh 能跑現(xiàn)象命令行virsh start正常qt-virt-manager 里點(diǎn)啟動(dòng)卻報(bào)Permission denied或Cannot access storage file。原因圖形程序啟動(dòng)時(shí)的環(huán)境變量和 shell 不一樣尤其是HOME、XDG_RUNTIME_DIR和用戶組。如果 qt-virt-manager 是通過(guò)桌面快捷方式啟動(dòng)的它可能沒(méi)有繼承你 shell 里的libvirt組。解決從終端直接運(yùn)行 qt-virt-manager 二進(jìn)制看報(bào)錯(cuò)是否消失。如果消失說(shuō)明是桌面啟動(dòng)器環(huán)境問(wèn)題改.desktop文件或直接用終端啟動(dòng)。另外檢查 AppArmor/SELinux 是否對(duì) qemu 進(jìn)程做了限制dmesg | grep -i denied能看到相關(guān)拒絕記錄。5.5 快照回滾后虛擬機(jī)起不來(lái)現(xiàn)象virsh snapshot-revert成功但虛擬機(jī)啟動(dòng)失敗報(bào)磁盤鏡像損壞或 backing file 找不到。原因外部快照的 backing chain 被破壞比如手動(dòng)刪了中間某個(gè)增量文件或者磁盤路徑變了。內(nèi)部快照一般不會(huì)這樣但如果你在快照后又手動(dòng)qemu-img改過(guò)文件也會(huì)出問(wèn)題。解決用qemu-img info --backing-chain看完整鏈條確認(rèn)每個(gè)文件都在。如果只是路徑變了用qemu-img rebase修正 backing file 路徑。最穩(wěn)的習(xí)慣是做快照前先virsh dumpxml備份 XML快照文件不要手動(dòng)碰回滾前先確認(rèn)虛擬機(jī)是關(guān)機(jī)狀態(tài)。6. 進(jìn)階把 qt-virt-manager 的能力接進(jìn)自己的 Qt 工具鏈如果你已經(jīng)能穩(wěn)定跑起 qt-virt-manager下一步大概率不是繼續(xù)用它而是想“我能不能在自己的 Qt 程序里也連 libvirt”。這條路是通的而且比想象中簡(jiǎn)單。核心就三步初始化 libvirt、建立連接、注冊(cè)事件。下面這段代碼展示了一個(gè)最小可用的連接和列表邏輯你可以直接放進(jìn)自己的 Qt 項(xiàng)目里。#include libvirt/libvirt.h #include QDebug // 初始化并連接 qemu:///system virConnectPtr conn virConnectOpen(qemu:///system); if (!conn) { qCritical() 連接 libvirt 失敗; return; } // 拿所有域虛擬機(jī) virDomainPtr *domains nullptr; int num virConnectListAllDomains(conn, domains, VIR_CONNECT_LIST_DOMAINS_ACTIVE | VIR_CONNECT_LIST_DOMAINS_INACTIVE); for (int i 0; i num; i) { const char *name virDomainGetName(domains[i]); virDomainInfo info; virDomainGetInfo(domains[i], info); qDebug() 虛擬機(jī): name 狀態(tài): info.state vCPU: info.nrVirtCpu 內(nèi)存(KB): info.memory; virDomainFree(domains[i]); } free(domains); virConnectClose(conn);參數(shù)說(shuō)明VIR_CONNECT_LIST_DOMAINS_ACTIVE | VIR_CONNECT_LIST_DOMAINS_INACTIVE表示同時(shí)列出運(yùn)行中和已關(guān)閉的域如果只要運(yùn)行中的去掉后半段。virDomainGetInfo返回的state是枚舉值VIR_DOMAIN_RUNNING是 1VIR_DOMAIN_SHUTOFF是 5界面上做狀態(tài)映射時(shí)別直接用數(shù)字。virDomainFree必須調(diào)否則每列一次就泄漏一個(gè)域?qū)ο箝L(zhǎng)時(shí)間運(yùn)行的工具會(huì)越來(lái)越卡。再進(jìn)一步如果你要做實(shí)時(shí)狀態(tài)更新把virConnectListAllDomains換成事件驅(qū)動(dòng)用virConnectDomainEventRegisterAny注冊(cè)VIR_DOMAIN_EVENT_ID_LIFECYCLE然后在回調(diào)里發(fā) Qt 信號(hào)。注意 libvirt 的回調(diào)是在它自己的線程里執(zhí)行的不能直接碰 UI 控件必須用QMetaObject::invokeMethod(obj, slot, Qt::QueuedConnection)切回主線程。這個(gè)細(xì)節(jié)不注意程序會(huì)隨機(jī)崩潰而且崩潰點(diǎn)看起來(lái)和 libvirt 毫無(wú)關(guān)系屬于典型的“血淚經(jīng)驗(yàn)”。最后一個(gè)實(shí)用技巧如果你要管理遠(yuǎn)程 libvirt 節(jié)點(diǎn)URI 寫(xiě)成qemussh://userhost/systemqt-virt-manager 和 libvirt 都支持。但 ssh 密鑰必須免密否則每次連接都彈密碼圖形界面會(huì)卡住。遠(yuǎn)程場(chǎng)景下事件回調(diào)的延遲比本地高做實(shí)時(shí)曲線時(shí)采樣間隔別低于 2 秒否則數(shù)據(jù)抖動(dòng)會(huì)很大。我自己現(xiàn)在的習(xí)慣是本地用qemu:///system做日常管理遠(yuǎn)程節(jié)點(diǎn)只在需要批量操作時(shí)用qemussh連一下平時(shí)不長(zhǎng)期掛著避免網(wǎng)絡(luò)抖動(dòng)導(dǎo)致界面假死。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取