全ての仮想マシンが停止したらホストをシャットダウンするスクリプト山市良のうぃんどうず日記(178)

本連載第174回では、Windows Server 2016の更新プログラムのインストール時に実行が重なると影響が大きいメンテナンスタスクについて、時短に役立つかもしれないコマンドラインのテクニックを紹介しました。今回はその応用です。

» 2020年05月13日 05時00分 公開
[山市良テクニカルライター]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「山市良のうぃんどうず日記」のインデックス

山市良のうぃんどうず日記

特定のプロセスを監視して終了後にシャットダウンするスクリプト

 本連載の第174回では、特に「Windows Server 2016」において、Windows Updateの更新プログラムのインストール処理と重なると影響が大きいバックグラウンド実行のメンテナンスタスクを、更新前または更新後に手動で実施することで、次回のWindows Updateの時短を図るコマンドラインのテクニックを紹介しました。

 その際に紹介したPowerShellスクリプト「myprocmon.ps1」は、Windows Server 2016のデスクトップエクスペリエンス環境で、自動クリーンアップ処理のためにバックグラウンドで実行される、または手動で実行した「ディスククリーンアップ」のプロセス(cleanmgr)の存在を定期的に確認し、プロセスが終了したら監視を終了するというものでした。cleanmgrプロセスが実行中の物理マシンや仮想マシンでこのスクリプトを実行すれば、後は放置しておいてもシャットダウンして停止してくれます。

 「\Microsoft\Windows\DiskCleanup\SilentCleanup」タスクの実行中、またはこのタスクに設定されたコマンドライン(cleanmgr.exe /autoclean /d C:)の手動実行と組み合わせて利用することを想定して作成しましたが、「Windows 10」で「ディスククリーンアップ」を実行し、「Windows Updateのクリーンアップ」を選択して、時間がかかるクリーンアップを実施するときにも活用できます(画面1画面2)。

while(1) {
    $procid = (Get-Process -ProcessName "cleanmgr" -ErrorAction SilentlyContinue).Id
    if ($procid.Length -eq 0) {
        Write-Host "cleanmgr not running currently"
	break
    } else {
        Write-Host "cleanmgr (PID" $procid ") is alive"
    }
    Start-Sleep -seconds 15
}
TIMEOUT 30
Stop-Computer -Force
▲「myprocmon.ps1」

画面1 画面1 PowerShellスクリプト「myprocmon.ps1」による「cleanmgr」プロセスの監視
画面2 画面2 自動クリーンアップ処理が完了すると「cleanmgr」プロセスが終了し、自動的にシャットダウンが始まる

全ての仮想マシンが停止したらHyper-Vホストを停止するスクリプト

 PowerShellスクリプト「myprocmon.ps1」を作成してからは、何かしらの処理の実行を開始して放置し、自動終了させるために、いろいろと重宝しています。Hyper-Vの仮想マシンのゲストOSで利用することが多いのですが、今回はHyper-Vホストの稼働状況と連動することも考えてみました。

 仮想マシンをゲストOS側から自動停止させることは、PowerShellスクリプト「myprocmon.ps1」やその応用でできるので、今回はHyper-Vホスト上の全ての仮想マシンが停止(または保存)状態になったらホストのシャットダウンを開始するというスクリプト「monitorvm.ps1」を作ってみました(画面3画面4)。

while(1) {
    $runningvms = 0
    $vmlist = (Get-VM -ErrorAction SilentlyContinue)
    if ($vmlist.Count -eq 0) {
        Write-Host "No virtual machines were found on this host."
	break
    } else {
	Clear-Host
        Write-Host "The current state of the virtual machines on this host:"
        Write-Host ""
        foreach ($vm in $vmlist) {
            Write-Host -NoNewLine "["
            if(($vm.State -eq "Off") -or ($vm.State -eq "Saved")) {
               Write-Host -NoNewLine $vm.State
            } elseif ($vm.State -eq "Running") {
               Write-Host -ForegroundColor "Green" -NoNewLine $vm.State
               $runningvms = $runningvms + 1
            } else {
               Write-Host -ForegroundColor "Yellow" -NoNewLine $vm.State
               $runningvms = $runningvms + 1
            }
            Write-Host "]"$vm.Name 
        }
    }
    Write-Host ""
    if ($runningvms -eq 0) {
        Write-Host "No virtual machines running on this host."
        break
    } else {
        Write-Host -ForegroundColor "Yellow" -NoNewLine $runningvms 
        Write-Host " virtual machines are currently running."
    }
    Start-Sleep -seconds 1
}
Write-Host -ForegroundColor "Red" "Start shutdown this host..."
Write-Host -ForegroundColor "Yellow" "Press Ctrl + C within 30 seconds to cancel shutdown"
TIMEOUT 30
Stop-Computer -Force
▲「monitorvm.ps1」

画面3 画面3 Hyper-Vホスト上の仮想マシンの実行状態を1秒間隔で監視
画面4 画面4 全ての仮想マシンが停止(Off)または保存(Saved)状態になったらホストのシャットダウンを開始する(30秒以内であれば[Ctrl]+[C]キーでシャットダウンを中止できる)

 このスクリプトは、Windows Server 2016以降のHyper-Vホスト、およびWindows 10のクライアントHyper-Vで動作することを確認しています。

 Hyper-Vホストで利用可能なWindows PowerShellの「Hyper-V」モジュールの「Get-VM」コマンドレットを利用して、1秒間隔で仮想マシンの状態を調査し、全ての仮想マシンが停止または保存状態の場合は30秒後にホストのシャットダウンを開始します。30秒以内なら[Ctrl]+[C]キーで中止できます。

 また、仮想マシンの状態が視覚的に分かるように、実行中(Running)の仮想マシンの状態は緑色で、実行中/停止/保存状態以外の状態は黄色で表示します。1秒間隔で監視していますが、監視間隔は「Start-Sleep」コマンドレットのパラメーターで調整可能です。

 ディスクの結合中やシャットダウン中など「Hyper-Vマネージャー」の「状況」列に表示される進行中の状態を含めて完全に完了するのを待ちたい場合は、「Get-VM」コマンドレットで取得できる「SecondaryOperationalStatus」属性を調べるとよいでしょう。ただし、通常は「状況」列で進行中の処理がシャットダウンにより中断されたとしても問題になることはありません。

Azure仮想マシンの確実なシャットダウンと停止への応用

 Microsoft Azure上のWindowsまたはLinux仮想マシンを、Azureポータル上から「停止」すると、ゲストOSのシャットダウン後に仮想マシンが停止され、割り当て解除状態になります。無駄な課金を回避するためには、割り当て解除の状態にすることが重要です。

 一方で、Azure側からの「停止」は、一定の時間が経過すれば、ゲストOSのシャットダウンを待たずに強制的に停止され、割り当て解除の処理に進みます。その場合、仮想マシンのゲストOSにとっては“強制的に電源がオフ”にされたのと同じなので、次回起動時にディスクの検査(chkdsk)が実行されたり、システムが破損して再起動を繰り返したりする場合もあるようです。

 今回紹介したPowerShellスクリプト「myprocmon.ps1」や「monitorvm.ps1」は、Azure仮想マシンを安全かつ確実にシャットダウンし、割り当て解除状態にするのに応用できます。

 PowerShellスクリプト「myprocmon.ps1」はWindows仮想マシン内で実行することで、ゲストOSのシャットダウンを自動化できます。「monitorvm.ps1」の「Get-VM」コマンドレットは、「Azure PowerShell」の「Az」モジュールの「Get-AzVM」に置き換えることができます。

 例えば、Azure PowerShellで次のコマンドレットを実行すると、割り当て解除状態であれば「PowerState/deallocated」と出力されます。

PS C:\> Get-AzureRmVM -Name "仮想マシン名" -ResourceGroupName "リソースグループ名" -Status| Select @{n="Status"; e={$_.Statuses[1].Code}}
Status
------
PowerState/deallocated

 「monitorvm.ps1」の「Stop-Computer」コマンドレットは、同じく「Az」モジュールの「Stop-AzVM」コマンドレットに置き換えることで、Azure仮想マシンの割り当て解除を行わせることができます。なお、古い「AzureRm」モジュールを利用している場合は、それぞれ「Get-AzureRmVM」と「Stop-AzureRmVm」に置き換えてください。パラメーターは共通のはずです。Azure仮想マシンを利用していて、ぜひともやってみたいという方は、以下の情報を参考にコーディングに挑戦してみてください。

筆者紹介

山市 良(やまいち りょう)

岩手県花巻市在住。Microsoft MVP:Cloud and Datacenter Management(2019-2020)。SIer、IT出版社、中堅企業のシステム管理者を経て、フリーのテクニカルライターに。Microsoft製品、テクノロジーを中心に、IT雑誌、Webサイトへの記事の寄稿、ドキュメント作成、事例取材などを手掛ける。個人ブログは『山市良のえぬなんとかわーるど』。近著は『Windows版Docker&Windowsコンテナーテクノロジ入門』(日経BP社)、『ITプロフェッショナル向けWindowsトラブル解決 コマンド&テクニック集』(日経BP社)。


Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。