【PowerShell】長時間バッチ処理中に停電でサーバーがシャットダウン!でも Workflow ならば安心です

Windows PowerShell 3.0 にはワークフロー機能が実装されています。もちろん、そのベースとなっているのは Windows Workflow Foundation 4.0 です。

例えば、以下のようなワークフローがあったとします。このワークフローでは、UserList.csv ファイルにの保存されたユーザー一覧を読みこんで、大量のユーザーを順次作成する処理を想定していると考えてください。

Workflow CreateUser {     Get-Content -Path \\junichia-vdi\tools\ps\wf\UserList.csv -Encoding String | `             Out-File -Path .\UserList_Unicode.csv -Encoding unicode     $UserList = Import-Csv -Path .\UserList_Unicode.csv     foreach  ($u in $UserList)     {         $UserID = $u.userID         Echo -InputObject "$(Get-Date) $UserID を作成します"         $password = convertto-securestring -Input $u.initialpassword -asplaintext -force         $Department = $u.Department         $FirstName = $u.FirstName         $LastName = $u.LastName         $HomeDirectory = \\Home\Share\$userID         InlineScript         {             New-ADUser `                -Name $using:UserID `                -AccountExpirationDate 2012/12/31 `                -AccountPassword $using:password `                -ChangePasswordAtLogon $using:true `                -Department $using:Department `                -GivenName $using:FirstName `                -Surname $using:LastName `                -HomeDirectory $using:HomeDirectory `                -HomeDrive "Z:" `                -ErrorAction SilentlyContinue `                -ErrorVariable ERRORMESSAGE

            If ($ERRORMESSAGE.Count -eq 0)             {               Echo -InputObject "$(Get-Date),$using:UserID を作成しました"             } else {               Echo -InputObject "$(Get-Date),$using:UserID $ERRORMESSAGE"             }         }         Checkpoint-Workflow     } }

ワークフローの実行までの流れは以下の通りです。

image

この例では、Invoke-Command を使用してリモートのドメインコントローラー上で、ワークフローをバックグラウンドジョブとして実行しています。

上図の左側に「Stopped」や「Running」と書かれているのはワークフローの状態です。

処理も半ばに差し掛かったころ、なんと停電の影響によりUPSからの指示でサーバーがシャットダウンを始めてしまいました。

このとき、ワークフローは自動的に「Syspended」という状態に移行します。

つまり、実行中のコマンドレットを、その状態ごとフリーズし保存してくれます。

ワークフロー内部で扱っていた変数や出力結果もそのまま残されています。

復電してドメインコントローラーが起動すると、ワークフローは自分ではレジュームできません。

管理者が再度ドメインコントローラーに接続して Resume-Job コマンドレットによりジョブを再起動してあげる必要があります。

通常、ジョブはサスペンドする直後からの処理を再開するので、ユーザー登録は漏れ無く実行することができます。

もし、UPS管理ソフトがコマンドを発行できるタイプであれば、シャットダウン前にジョブをサスペンドし、次回起動時に自動的にレジュームするようスケジューリングすることもできます。

VBSを使用していた時代は、サーバーが落ちたりクライアントが落ちると、ログを解析して続きのバッチを組みなおさなければなりませんでしたが、PowerShell 3.0 ではワークフローによって不測の事態の復旧が、とても簡単になりました。