かつて山市良と呼ばれたおじさんのブログ

セイテクエンジニアのブログ  かつて山市良と呼ばれたおじさんのブログ  vol.236 Get-VMで状態を取得する裏技の応用|Hyper-V 小技・裏技集

 

 

vol.236 Get-VMで状態を取得する裏技の応用|Hyper-V 小技・裏技集

2026年09月24日配信
執筆者:山内 和朗

 「Hyper-V小技・裏技集」シリーズでは、Hyper-Vの仮想環境を利用していて、知っていると便利な小技や裏技を紹介します。今回は、前回紹介したGet-VMによる状態監視の基本スクリプトの応用です。

 

※ここで紹介するサンプルコードは、PowerShellスクリプト(.ps1)内に記述することを想定しています。-ErrorAction Stopパラメーターは、エラー時にスクリプト全体を停止します。PowerShellウィンドウに入力して実行した場合は、エラーが発生しても以後のスクリプトは停止しないため、別のエラーが発生する可能性があることに注意してください。

 

VMを再起動

 

 PowerShellのHyper-Vモジュールには、開始(Star-VM)、シャットダウンまたは停止(Stop-VM)、保存(Save-VM)などVMの電源を操作するコマンドラインが用意されていますが、再起動のためのコマンドラインは存在しません。Restart-VMは再起動に対応しているように見えるかもしれませんが、このコマンドレットはVMをリセット(ハードリセット)するものであり、ゲストOSから見れば電源を突然オフ/オンされることに相当します。

 前回紹介したVMの開始とゲスト起動完了まで、VMのシャットダウン開始と停止までの基本のPowerShellスクリプトを組み合わせれば、VMのゲストOSの再起動を簡単に実装できます。次の2つのスクリプトはVMのゲストOSの再起動を実装した例です(画面1)。
  

$vmName = "vm01"
$vm = Get-VM -Name $vmName -ErrorAction Stop
$vm |Stop-VM -Force -ErrorAction Stop
do {
    Start-Sleep -Seconds 1
} until ($vm.State -like "Off")
Write-Host "$($vm.Name) is Off.Start VM..."

$vm = Get-VM -Name $vmName -ErrorAction Stop
$vm |Start-VM -ErrorAction Stop
do {
    Start-Sleep -Seconds 1
} until ($vm.Heartbeat -like "Ok*")
Write-Host "$($vm.Name) is Rebooted."

プレーンテキストでダウンロード/表示) 

$vmName = "vm01"
$vm = Get-VM -Name $vmName -ErrorAction Stop
$vm |Stop-VM -Force -ErrorAction Stop
while($vm.Heartbeat -like "Ok*") {
  Start-Sleep -Seconds
}
Write-Host "$($vm.Name) is Off. Start VM..."
$vm = Get-VM -Name $vmName -ErrorAction Stop
$vm |Start-VM -ErrorAction Stop
while($vm.Heartbeat -notlike "Ok*") {
  Start-Sleep -Seconds 1
}
Write-Host "$($vm.Name) is Rebooted."

プレーンテキストでダウンロード/表示)
※これらのスクリプトでは、Get-VM($vm = Get-VM -Name $vmName)を2回実行しています。2回目のGet-VMを実行しない場合、$vm.HeartBeatに古い値(OkApplications*)が出現することがありました。2回目のGet-VMの代わりに、Start-Sleep 2を実行して値が更新されるまで待機することで古い値が出現する問題を回避することもできました。

 

画面1 Hyper-Vホスト側からVMを再起動するPowerShellスクリプトの実行例
画面1 Hyper-Vホスト側からVMを再起動するPowerShellスクリプトの実行例

 

VMの起動順序を制御

 

 Active Directoryのドメインコントローラー、データベースサーバー、アプリケーションサーバーなど、依存関係のある複数のVMで構成されたシステムでは、前提となるサービスが利用可能になったことを確認しながら順番に起動したいというニーズがあります。そのようなニーズも、VMの開始とゲスト起動完了までの基本のPowerShellスクリプトを利用すれば簡単に実現できます。以下のスクリプトは、最初にvm01を開始し、vm01のゲストOSの起動が完了したら、vm02を開始します(画面2)。

 

$vmName = "vm01"
$vm = Get-VM -Name $vmName -ErrorAction Stop
$vm |Start-VM -ErrorAction Stop
do {
    Start-Sleep -Seconds 1
} until ($vm.Heartbeat -like "Ok*")
Write-Host "$($vm.Name) is Up."

$vmName = "vm02"
$vm = Get-VM -Name $vmName -ErrorAction Stop
$vm |Start-VM -ErrorAction Stop
do {
    Start-Sleep -Seconds 1
} until ($vm.Heartbeat -like "Ok*")
Write-Host "$($vm.Name) is Up."

プレーンテキストでダウンロード/表示)

 

 画面2 vm01を開始し、ゲストOSが起動したら(ハートビートが“Ok*”になったら)、vm02を開始するスクリプトの例
画面2 vm01を開始し、ゲストOSが起動したら(ハートビートが“Ok*”になったら)、vm02を開始するスクリプトの例

 

VMグループの起動を待機

 

 Windows Server 2016のHyper-Vからは、複数のVMをグループ化する「仮想マシングループ(以下、VMグループ)」という機能が利用可能になりました。VMグループを利用すると、グループ単位で管理操作を実行できます。例えば、複数のVMで構築されたフェールオーバークラスターを同時に起動したりできます。

 

 VMグループはNew-VMGroupを使用して作成でき、Add-VMGroupMemberを使用して1台以上のVMをグループのメンバーに追加できます。

New-VMGroup -Name "mycluster" -GroupType VMCollectionType
Add-VMGroupMember -Name "mycluster" -VM (Get-VM "VM名)

 

 次のPowerShellスクリプトは、VMグループ「mycluster」のメンバーのすべてのVMを1回のStart-VM操作で開始し、各ノードのゲストOSが起動するまで待機するスクリプトです(画面3)。

 

$vms = (Get-VMGroup -Name "mycluster").VMMembers
$vms
$vms |Start-VM -ErrorAction Stop
foreach ($vm in $vms) {
    while ($vm.Heartbeat -notlike 'Ok*') {
        Start-Sleep 1
    }
    Write-Host "$($vm.Name) is Up."
}

プレーンテキストでダウンロード/表示)

 

 画面3 VMグループのメンバーのVMを一括で開始し、ゲストOSが起動するまで待機するPowerShellスクリプトの実行例
画面3 VMグループのメンバーのVMを一括で開始し、ゲストOSが起動するまで待機するPowerShellスクリプトの実行例

 

アプリケーションを監視し、再起動で復旧

 

 SQL ServerなどHyper-Vのアプリケーションレベルの監視に対応している場合は、HeartBeatプロパティ“OkApplicationsHealthy(OK (アプリケーション データ正常))”を監視できます。しかし、“OkApplicationsHealthy”はHyper-Vがサービスを監視しているわけではありません。アプリケーション自らが異常をHyper-Vに通知する仕組みが機能していると考えてください。異常を検知する仕組みとしては機能しますが、アプリケーション側に通知する仕組みが実装されていなければ意味はありません。例えば、SQL Serverの場合、サービス(MSSQLServer)を強制終了してもHeartBeatプロパティは“OkApplicationsHealthy”のままです。

 ネットワーク経由でデータベースの接続性やWebアプリケーション/サイトの接続性を確認できる場合は、PowerShellで比較的簡単に実装できます。次のPowerShellスクリプトは、VMがホストするURLにアクセスし、HTTPステータスコード200であれば正常、他のステータスコードや接続失敗の場合は、VMを再起動(またはリセット)して復旧を試みる例です(画面4)。

 

$vmName = "vm01"
$vm = Get-VM -Name $vmName -ErrorAction Stop
$appurl = "https://www.say-tech.co.jp"
while ($vm.State -eq "Running") {
  $ret = $null
  $ret = Invoke-WebRequest -Uri $appurl -UseBasicParsing -TimeoutSec 10 -ErrorAction SilentlyContinue
  if ($ret -ne $null -and $ret.StatusCode -eq 200) {
       Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') app is online   " -ForeGroundColor Green
  } else {
      Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') app is Down.     " -ForeGroundColor Red
      Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') Restart VM ...   " -ForeGroundColor Red
      #Restart-VM -Name $vm.Name -Force
      #Start-Sleep 60
      $vm |Stop-VM -Force -ErrorAction Stop
      while($vm.Heartbeat -like "Ok*") {
          Start-Sleep -Seconds 1
      }
      $vm |Start-VM -ErrorAction Stop
      Start-Sleep -Seconds 2
      while($vm.Heartbeat -notlike "Ok*") {
          Start-Sleep -Seconds 1
      }
      Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') VM Restarted."
  }
  Start-Sleep 60
}

プレーンテキストでダウンロード/表示)

 

画面4 アプリケーション(Web)を監視し、動作していない場合はVMの再起動(またはリセット)で復旧するPowerShellスクリプトの実行例
画面4 アプリケーション(Web)を監視し、動作していない場合はVMの再起動(またはリセット)で復旧するPowerShellスクリプトの実行例

 

リファレンス(Microsoft Learn):
Get-VM(Hyper-V)Start-VM(Hyper-V)Stop-VM(Hyper-V)New-VMGroup(Hyper-V)| Add-VMGroupMember(Hyper-V)| Get-VMGroup(Hyper-V)| Checkpoint-VM(Hyper-V)

Hyper-V 小技・裏技集 (1)(2)(3)(4)(5)

blog_yamanxworld_subscribe

blog_yamanxworld_comment

blog_yamanxworld_WP_ws2025

最新記事