8 phút đọc
Insights / Troubleshooting

VMware Workstation không bật được VM sau khi máy tính tắt đột ngột

Công Hoàng Anh
Đăng ngày 26/09/2026
VMware Workstation không bật được VM sau khi máy tính tắt đột ngột

Mình thấy các tác giả/chuyên gia của hệ sinh thái chia sẻ rất nhiều kinh nghiệm thực tế hữu ích, mình học hỏi được rất nhiều. Tuy nhiên, mình thấy một vài kiến thức đơn giản mà nhiều bạn mới hay gặp thì chưa được chia sẻ nhiều (chắc tại research AI là ra hoặc các bác pro thường không có nhiều thời gian nên chỉ chia sẻ kiến thức hữu ích) nên mình nay chia sẻ case này dành cho các bạn mới nhé.

Anh em học và làm DevOps việc lab tryhard để lên trình là điều rất thường ngày rồi và VMware Workstation là công cụ rất điển hình để tạo các server làm lab.

Và trường hợp tắt máy tính đột ngột và khi mở lại không bật được server là điều rất hay gặp nên mình chia sẻ để mọi người gặp đúng trường hợp này thì đỡ mất thời gian nhé.

Bài toán

Máy Windows của đang chạy bị tắt đột ngột trong lúc một số VM vẫn đang chạy.

Sau khi bật máy lên lại thì các VM khác vẫn chạy bình thường, riêng một VM không thể start được. VMware báo lỗi kiểu:

The process cannot access the file because another process has locked a portion of the file

Cannot open the disk

Module Disk power on failed

Failed to start the virtual machine

Nhìn qua thì khá dễ nghĩ VMDK có vấn đề vì máy vừa bị tắt đột ngột.

Nguyên nhân là VMware vẫn còn các lock từ lần chạy trước.

Điểm quan trọng là không nên thấy .lck rồi xóa ngay. Trước khi xóa cần biết lock đó là lock cũ do máy tắt ngang hay vẫn đang được một process VMware sử dụng.

1. Đầu tiên tìm xem process nào đang giữ VM

Khi VM chạy, VMware Workstation sử dụng process:

vmware-vmx.exe

Ngay sau khi gặp lỗi, mở PowerShell và chạy:

Get-CimInstance Win32_Process |
Where-Object Name -eq 'vmware-vmx.exe' |
Select-Object ProcessId, CommandLine |
Format-List

Nếu còn vmware-vmx.exe, phần CommandLine sẽ cho mình khá nhiều thông tin.

Ở cuối command thường có đường dẫn tới file .vmx của VM.

Dạng như:

...\vmware-vmx.exe ... msgs=ui D:\...\server.vmx

Nhờ vậy mình không cần biết trước VM nằm ở thư mục nào.

Nếu đang chạy nhiều VM thì sẽ có nhiều vmware-vmx.exe. Có thể dùng đoạn PowerShell dưới đây để nhìn rõ PID, tên VM và đường dẫn VMX của từng process.

$VMXList = Get-CimInstance Win32_Process |
Where-Object Name -eq 'vmware-vmx.exe' |
ForEach-Object {
    if ($_.CommandLine -match 'msgs=ui\s+(.+\.vmx)\s*$') {
        $vmx = $Matches[1]

        $displayName = Select-String `
            -LiteralPath $vmx `
            -Pattern '^displayName\s*=' |
            Select-Object -First 1

        [PSCustomObject]@{
            ProcessId  = $_.ProcessId
            DisplayName = (
                $displayName.Line -replace '^displayName\s*=\s*', ''
            ).Trim([char]34)
            VMX = $vmx
        }
    }
}

$VMXList | Format-Table -AutoSize

Kết quả sẽ có dạng:

ProcessId   DisplayName            VMX
---------   -----------            ---
19136       my-server              D:\...\my-server.vmx

Từ đây mình biết chính xác file VMX của con VM đang lỗi.

2. Lưu VMX vào biến để khỏi phải sửa path trong từng lệnh

Sau khi đã nhìn thấy PID của VM đang lỗi, mình chọn PID đó:

$TargetPid = [int](Read-Host 'Nhap ProcessId cua VM dang loi')

$VMX = (
    $VMXList |
    Where-Object { $_.ProcessId -eq $TargetPid }
).VMX

$VMX

Từ đây các lệnh phía sau đều dùng $VMX.

Không cần hardcode đường dẫn của máy mình hay của bất kỳ ai.

3. Từ VMX tìm toàn bộ VMDK mà VM đang sử dụng

Một VM có thể chỉ có một disk nhưng cũng có thể attach thêm nhiều VMDK nằm ở thư mục khác.

Mình không đoán disk nằm ở đâu mà đọc trực tiếp từ file VMX.

$VMDir = Split-Path -LiteralPath $VMX -Parent

$VMDKs = Select-String `
    -LiteralPath $VMX `
    -Pattern 'fileName\s*=\s*"([^"]+\.vmdk)"' |
ForEach-Object {

    $DiskPath = $_.Matches[0].Groups[1].Value

    if ([System.IO.Path]::IsPathRooted($DiskPath)) {
        [System.IO.Path]::GetFullPath($DiskPath)
    }
    else {
        [System.IO.Path]::GetFullPath(
            (Join-Path $VMDir $DiskPath)
        )
    }
}

$VMDKs

Ví dụ VMX có:

scsi0:0.fileName = "Ubuntu-server.vmdk"
scsi0:1.fileName = "D:\vm-disks\data.vmdk"

Script sẽ tự chuyển thành đường dẫn đầy đủ của cả hai VMDK.

Chỗ này khá quan trọng vì case của mình có một disk nằm cùng VM và một disk nằm ở thư mục khác.

4. Trước khi xóa lock phải chắc chắn VM đã tắt

Sau khi đã biết VMX và các VMDK liên quan, mình shutdown bình thường toàn bộ VM còn đang chạy rồi đóng VMware Workstation.

Sau đó kiểm tra lại:

Get-CimInstance Win32_Process |
Where-Object Name -eq 'vmware-vmx.exe'

Nếu không có output thì hiện tại không còn vmware-vmx.exe.

Mình kiểm tra thêm bằng vmrun.

Đoạn này tự tìm vmrun.exe ở hai vị trí cài VMware Workstation thường gặp:

$VMRun = @(
    (Join-Path ${env:ProgramFiles(x86)} 'VMware\VMware Workstation\vmrun.exe'),
    (Join-Path $env:ProgramFiles 'VMware\VMware Workstation\vmrun.exe')
) |
Where-Object { Test-Path -LiteralPath $_ } |
Select-Object -First 1

& $VMRun list

Kết quả mình cần thấy là:

Total running VMs: 0

Case của mình lúc này có đủ hai điều kiện.

Total running VMs: 0

và không còn:

vmware-vmx.exe

Máy trước đó lại vừa bị tắt đột ngột trong lúc VM đang chạy.

Lúc này khả năng các .lck còn lại là lock cũ khá rõ.

5. Tìm đúng các lock liên quan đến VM

Thay vì scan cả ổ đĩa rồi xóa tất cả .lck, mình chỉ lấy lock liên quan đến VMX và các VMDK vừa tìm được.

$Locks = @()

$VMXLock = $VMX + '.lck'

if (Test-Path -LiteralPath $VMXLock) {
    $Locks += Get-Item -LiteralPath $VMXLock -Force
}

foreach ($VMDK in $VMDKs) {

    $VMDKLock = $VMDK + '.lck'

    if (Test-Path -LiteralPath $VMDKLock) {
        $Locks += Get-Item -LiteralPath $VMDKLock -Force
    }
}

$Locks += Get-ChildItem `
    -LiteralPath $VMDir `
    -Force `
    -Filter '*.vmem.lck' `
    -ErrorAction SilentlyContinue

$Locks = $Locks |
Sort-Object FullName -Unique

$Locks |
Select-Object FullName, PSIsContainer

Trong case của mình nó tìm ra các dạng:

server.vmx.lck
system-disk.vmdk.lck
data-disk.vmdk.lck
xxxxxxxx.vmem.lck

Bên trong các thư mục này có thể còn những file kiểu:

M31454.lck
M06851.lck

Đó cũng là một phần của lock.

6. Xóa stale lock

Chỉ làm bước này khi mọi người đã kiểm tra:

Total running VMs: 0

và:

vmware-vmx.exe

không còn tồn tại.

Mình cho PowerShell hiện lại toàn bộ thứ sắp xóa trước:

$Locks |
Select-Object FullName, PSIsContainer

Sau đó mới xác nhận:

$Confirm = Read-Host 'Nhap YES neu da chac chan khong con VM nao dang chay'

if ($Confirm -ceq 'YES') {

    $Locks |
    Sort-Object { $_.FullName.Length } -Descending |
    Remove-Item -Recurse -Force

    Write-Host 'Da xoa cac stale lock'
}
else {
    Write-Host 'Khong co gi bi xoa'
}

Mình cố tình không viết script tự xóa ngay.

Với loại lỗi này, mình vẫn muốn nhìn danh sách lock một lần trước khi cho Remove-Item chạy.

7. Những file không được đụng tới

Phần mình xóa ở trên chỉ là .lck.

Không xóa các file như:

.vmdk
-flat.vmdk
-delta.vmdk
-sesparse.vmdk
.vmx
.vmem
.vmsd
.vmsn

Nhất là:

-flat.vmdk
-delta.vmdk
-sesparse.vmdk

Đây có thể là dữ liệu disk hoặc snapshot thật của VM.

Xóa nhầm những file này thì câu chuyện không còn là xử lý lock nữa.

8. Kết quả

Sau khi xóa các .lck cũ, mình mở VMware Workstation và start lại VM.

Máy lên bình thường.

Không cần repair VMDK, không cần restore snapshot và cũng không phải tạo lại VM.

Nguyên nhân trong case này đơn giản là máy tính bị tắt đột ngột khi VM vẫn chạy, VMware không kịp dọn lock, lần boot sau nhìn thấy lock cũ nên không cho mở disk.

Một lưu ý cuối

Nếu sau khi xử lý .lck mà lỗi lock biến mất nhưng VMware chuyển sang báo những lỗi như:

The file specified is not a virtual disk

The parent virtual disk has been modified

The disk needs repair

thì nên dừng ở đó.

Lúc này vấn đề có thể đã chuyển sang VMDK descriptor hoặc snapshot chain, không còn là case stale lock như bài này nữa.

Còn nếu mọi người vừa bị mất điện, Windows crash hoặc máy bị tắt ngang trong lúc VMware đang chạy, sau đó gặp:

The process cannot access the file because another process has locked a portion of the file

thì mình nghĩ nên kiểm tra vmware-vmx.exe, tìm VMX, lần từ VMX ra VMDK rồi xác nhận không còn VM nào chạy trước khi đụng tới .lck.

Đó cũng chính là cách mình xử lý case này và VM đã chạy lại bình thường.

Chia sẻ bài viết

Theo dõi
Thông báo của
0 Góp ý
Được bỏ phiếu nhiều nhất
Mới nhất Cũ nhất
Đã sao chép liên kết vào bộ nhớ tạm!