WSFCに登録可能な汎用スクリプトについて

# はじめに

はじめまして。Windows勉強中の
なおきち餃子（[@naokichigyoza](https://twitter.com/naokichigyoza)）と申します。


Windows Server でクラスタ環境を構築した際に、
フェールオーバークラスタに「汎用スクリプト」が登録できますが
登録にあたっては、いくつかの制約があります。

これらの制約をまとめ、実際に登録可能なスクリプト例を紹介します。

# 登録可能な「汎用スクリプト」の仕様

Visual Basic Script（.vbs）ファイル のみ登録可能です。

.vbs ファイル内では、「エントリポイント関数」と呼ばれる
いくつかの関数を定義する必要があります。

処理を実行したいタイミングに応じて、適切なエントリポイント関数内に処理を記載することで
処理の実行タイミングの制御が可能です。

| エントリポイント関数名 | 実行タイミング |
|:-:|:-:|
| Open 関数 | 登録したスクリプトファイルが開かれた際に実行|
| Online 関数 | リソースがオンラインになった際に実行 |
| LooksAlive 関数（必須） | 5秒ごとに実行（リソース稼働状況の簡易チェックに利用） |
| IsAlive 関数（必須） | 60秒ごとに実行（リソース稼働状況の厳密チェックに利用） |
| Offline 関数 | リソースがオフラインになった際に実行 |
| Close 関数 | 登録したスクリプトファイルが閉じられた際に実行 |
| Terminate 関数 | 登録したスクリプトファイルが強制終了した際に実行 |

LooksAlive 関数 および、IsAlive 関数 は必須です。
これらを .vbs ファイルに含めないと、エラーとなり登録ができません。


エントリポイント関数の戻り値が、数値の 0 か ブール値の "true" の場合は
関数の実行が成功とみなされます。
戻り値が関数内で設定されていない場合も、成功とみなされます。

エントリポイント関数の戻り値が、数値の 0 以外、またはブール値の "false" の場合は、
関数の実行が失敗とみなされ、クラスターログに記録されます。

なお、必須である LooksAlive 関数 および、IsAlive 関数 の戻り値を関数内で指定する場合は、
数値ではなく、ブール値の "true" または "false" を指定する必要があります。

詳しくは以下のマイクロソフト社の技術資料を参照。

https://learn.microsoft.com/ja-jp/previous-versions/windows/desktop/mscs/scripting-entry-points

# 実際に登録可能な汎用スクリプトのサンプル

現在時刻と、""スクリプトが実行されました"" という文字列を
共有フォルダに配置したテキストファイルに追記する .vbs ファイルを作成しました。

```vb:sample.vbs
Option Explicit

Function LooksAlive( )
Dim fso, logFile, logText,  result
result = false

On Error Resume Next

' 書き込むテキストファイルのパスを設定、ファイルの場所に応じ適宜変更ください
Set fso = CreateObject("Scripting.FileSystemObject")
Set logFile = fso.OpenTextFile("\\[サーバー名]\Share\test.log", 8, True)

' 現在時刻とメッセージを取得
logText = Now() & " - スクリプトが実行されました"

' テキストファイルにメッセージを書き込む
logFile.WriteLine logText

' テキストファイルを閉じる
logFile.Close

' エラーが発生していない場合はTrueを返す
If Err.Number = 0 Then
result = true
'エラー情報をクリアする
Err.Clear
End If

' エラー処理を元に戻す
On Error Goto 0

' 戻り値を返す
LooksAlive = result
End Function

Function IsAlive( )
IsAlive = true
End Function
```

上記を実際に登録したところ、LooksAlive 関数に処理を記載したため
5秒ごとにテキストファイルへ追記されていることが確認できました。

```py:出力結果（test.log）
2023/04/25 12:15:28 - スクリプトが実行されました
2023/04/25 12:15:33 - スクリプトが実行されました
2023/04/25 12:15:38 - スクリプトが実行されました
```

テキストファイルを書き込み不可とし、意図的にエラーを発生させると
エラーが記録されることも確認できました。

```yaml:WSFC の クラスターイベント で確認できたエラーログ
レベル: エラー
日付と時刻: 2023/04/25 12:25:38
ソース: Microsoft-Windows-FailoverClustering
イベントID: 5401
タスクのカテゴリ   : なし
""[RES] Generic Script <sample スクリプト>: 'LooksAlive' script entry point returned FALSE.'""
```


# （おまけ）.vbs ファイル以外を登録したい場合

前述の通り、「汎用スクリプト」には
Visual Basic Script（.vbs）ファイル のみ登録可能ですが
以下の2つの方法を用いることで、バッチファイル（.bat）や、
PowerShell のスクリプト（.ps1）の処理を実行させることが可能です。

## 1.　.bat や .ps1 ファイルを呼び出す .vbs ファイルを作成する

以下のように、任意のエントリポイント関数内に
.bat ファイル、または .ps1 ファイルを実行する処理を記載することで
.bat ファイルや .ps1 ファイルに記載の処理内容を登録することが可能です。

```vb
Function LooksAlive( )
Dim objShell
Set objShell = CreateObject(""WScript.Shell"")
objShell.Run ""cmd /c 【.batファイルのフルパス】""
objShell.Run ""powershell.exe -ExecutionPolicy Bypass -File 【.ps1ファイルのフルパス】""
Set objShell = Nothing
LooksAlive = true
End Function
```

## 2.　「汎用アプリケーション」として登録する

.bat ファイル、または .ps1 ファイルは、「汎用スクリプト」ではなく
「汎用アプリケーション」としてであれば、フェールオーバークラスタに直接登録可能です。

別途 .vbs ファイルを作成する必要はありませんが、処理実行タイミングの細かな制御が出来ず、
フェールオーバー発生時に、1度のみ処理が実行される形となります。


# 終わりに
WSFCに、汎用スクリプトを実際に登録してみた情報が
WEB上に見当たらなかったので公開しました。
どなたかのお役に立てれば幸いです。


Twitter
https://twitter.com/naokichigyoza


https://naokichigyoza.com