2025年1月13日 星期一

[vm] Pause all VM instances if a running instances do not active for a long time

Pause all VM instances if a running instances do not active for a long time.

井民全, Jing, mqjing@gmail.com


使用 VirtualBox 常常遇到 VM XDM does not respones any user input when the Windows host backed from sleep or hibernate. If I got this, a comon solution is ssh to the VM and restart the gdm by folloing command. 
sudo systemctl restart gdm 
Follow the procedure that will pause all VM instances if you do not touch the VM for a long time. It will prevent the XDM issue when the host backed from the sleep.

1. Concept

  1. 目前無法讓 VM 在系統即將進入 sleep 模式時, 收到 Windows 事件通知. 所以改用 AutoHotKey (download)

2. Pause all VM (script)

Windows Batch file

@ECHO OFF

REM 列出所有正在運行的虛擬機

FOR /F "tokens=1 delims= " %%i IN ('VBoxManage list runningvms') DO (

    ECHO 暫停虛擬機: %%i

    VBoxManage controlvm "%%i" pause

)

ECHO 所有虛擬機已暫停。

PAUSE


E.g.

File: pause_all_vm.bat

@ECHO OFF

REM List all running VM instances

FOR /F "tokens=1 delims= " %%i IN ('"C:\Program Files\Oracle\VirtualBox\VBoxManage" list runningvms') DO (

    ECHO Pause the instance: %%i

    "C:\Program Files\Oracle\VirtualBox\VBoxManage" controlvm "%%i" pause

)

ECHO All instances are paused.

PAUSE



3. AutoHotkey script

File: pause_al_vm.ahk

#Requires AutoHotkey v2.0


SetTitleMatchMode("RegEx") ; 

windowTitle := ".*Running.*" 

inactiveTime := 60*1000 ; Time in milliseconds (e.g., 60000 ms = 1 minute)

checkInterval := 1000 ; Interval to check the window status in milliseconds

idleDuration := 0


MsgBox ("AuotHotKey script Begin")

batFilePath := "pause_al_vm.bat"


SetTimer(CheckWindow, checkInterval)


CheckWindow() {

    global windowTitle, inactiveTime, idleDuration

    

    if WinExist(windowTitle) && !WinActive(windowTitle) { ; Check if the window exists and is not active

        idleDuration += checkInterval ; Increment idle duration

        if (idleDuration >= inactiveTime) {

            MsgBox("AuotHotKey: Run pause all VM instances batch.")

            Run(batFilePath)

            idleDuration := 0 ; Reset idle duration after action

        }

    } else {

        idleDuration := 0 ; Reset if the window is active or does not exist

    }

}


Esc::

{

    ; Display a message box with Yes and No options

    if (MsgBox("Are you sure you want to exit the script?", "Exit Confirmation", 4) == "Yes")

    {

        ExitApp  ; Exit if the user clicks Yes

    }

}