以前の記事で作成したバッチファイルを機能追加して、もうちょっと監視っぽく改善したのでご報告です。
scコマンドでWindowsサービス監視していたバッチファイルの件。
以前の記事
概要としては、Windowsのサービスを監視して、停止していたら起動してログに記録する、という動作をするバッチファイルを作成し、タスクスケジューラで実行していました。
どのようなバッチファイルだったかの詳細は、以前の記事をご覧ください。
■一つ前
■大元の記事
(1/3)Windowsサービス監視 - treedown’s Report
(2/3)Windowsサービス監視 - treedown’s Report
(3/3)Windowsサービス監視 - treedown’s Report
元々、この「(3/3)Windowsサービス監視」のページ内に「自力でlogrotate」という項でログファイルの肥大化を別のバッチで実行するようにしていました。
改善点
今回は、前述のサービス監視&自動起動バッチに以下の機能を追加しようと思います。
- ログローテーション機能
ログが増えっぱなしなので、せめて一定期間でリネームしてファイルを新しくしよう。
元々別のバッチでファイル更新をするようにしていたのですが、サービス監視のバッチ内にその処理を入れてしまおうという試みです。
- アラートメール送信機能
サービス起動の処理が実行された時だけアラートメールが送信されるようにしたい。
ただ、メール送信はPowerShellの力が必要。ここだけはPowerShellで用意して、バッチファイルからは「Powershell -command」で.ps1ファイルを実行するようにします。
完成したバッチファイル
まずは完成したバッチファイルを。
※バッチファイルはパス名やサービス名、ファイル名などを変更する必要があります。
ファイルは二つのファイルを使います。同じフォルダにファイルを置いて動作確認しました。
--------------------------------------------------------------
svc-chk.bat ※実行ファイル:ここで監視や動作を実行
--------------------------------------------------------------
@echo off
rem -------------------------------------------------------------------------
rem サービスを監視し、停止時には自動起動するバッチファイルです。
rem 自動起動時にはメールで通知、ファイル名:DW-mailbody.ps1を使います。
rem 年に一回ログローテーションでログファイルsvc.logを再生成します。
rem -------------------------------------------------------------------------
rem 監視するサービス名
rem set SERVICE=Dhcp
set SERVICE=PSEXESVC
rem ログの出力パス
set LOG=C:\temp\svc.log
rem 今日の日付取得
set Today=%date:~0,4%-%date:~5,2%-%date:~8,2%
set daymmdd=%Today:~5,2%%Today:~8,2%
rem ローテーション用の日付(1月1日は0101)
set rotateday=1231
rem アラートメール送信用ファイルパス
set MailPs=C:\temp\mailbody.ps1
rem サービスの起動確認
sc.exe query "%SERVICE%" | find "STATE" | find "RUNNING" > nul
if %ERRORLEVEL% == 1 goto svcstart
if %ERRORLEVEL% == 0 goto noexec
:svcstart
echo %Today% %TIME% %COMPUTERNAME% "%SERVICE%" isn't running. >> %LOG%
echo %Today% %TIME% %COMPUTERNAME% "start ServiceNAME=%SERVICE% Service" >> %LOG%
net start "%SERVICE%"
if %ERRORLEVEL% equ 0 (
echo %Today% %TIME% %COMPUTERNAME% "%SERVICE%"Service started. >> %LOG%
) else (
echo %Today% %TIME% %COMPUTERNAME% "%SERVICE%"Service Unexpected error: service may not have started. >> %LOG%
)
Powershell -command "%MailPs%"
goto logrotateY
:noexec
echo %Today% %TIME% %COMPUTERNAME% %SERVICE% is running. >> %LOG%
goto logrotateY
:logrotateY
rem echo 日付を確認して、特定の日にlogrotateを実行します。
rem echo %daymmdd% EQU %rotateday%の比較
if %daymmdd% EQU %rotateday% (
rem echo daymmddとrotatedayは合致しました。
SET COPYCMD=/Y
RENAME "%LOG%" svc%Today%.log
rem echo "%LOG% は、svc%Today%.log に名前を変更しました。
SET COPYCMD=
goto end
) else (
rem echo daymmddとrotatedayは合致しません。
goto end
)
:end
rem 後処理
set SERVICE=
set LOG=
set Today=
set daymmdd=
set rotateday=
set MailPs=
--------------------------------------------------------------
もう一つのファイルは、メール送信を担当する.ps1ファイルです。
--------------------------------------------------------------
mailbody.ps1 ※関連ファイル、メール送信処理を担当、PowerShell
--------------------------------------------------------------
#アラートメール送信シェル
$From = "hoge@hogehoge.net"
$Reply = "hoge@hogehoge.net"
$SMTPServer = "smtp.hogehoge.net"
$Port = 587
$UserName = "hoge@hogehoge.net"
$Password = "%PASSWORD%"
$SMTPClient=New-Object Net.Mail.SmtpClient($SMTPServer,$Port)
$SMTPClient.EnableSSL=$false
$SMTPClient.Credentials=New-Object Net.NetworkCredential($UserName,$Password)
#メール本文
$To = "hoge@hogehoge.net"
$Subject = "○○サービス起動監視"
$body = "○○サービスが起動していなかったので、スタートを試みました。`r`n"
$body += "サービスの状態を確認してください。"
#メール送信実行
$Mail=New-Object Net.Mail.MailMessage($From,$To,$Subject,$body)
$SMTPClient.Send($Mail)
--------------------------------------------------------------
ここまでがバッチファイルと.ps1ファイルです。
今回は仮に、
<C:\temp>に配置して動作を確認していました。作成したsvc-chk.batをタスクスケジューラなどに登録して自動実行させていきます。
ちょっと解説
編集箇所も含めて、ちょっと解説していきます。
- ログローテーション機能
以前<バッチファイルで日付を比較して条件分岐 - treedown’s Report>にて、日付の比較を動作確認しました。これを使って今日の日付を4桁<MMDD>で取得して、ラベル「:logrotateY」以下で比較し、合致しない場合には何もせず終了しますが、合致した場合には、ログローテーションの処理を挿入しています。(1年で1ファイル)
ログは前回と同じ。
サービスが起動しているかどうかを確認してログに記録していきますし、サービスが起動してない場合には起動を試みて結果を記録していきます。
- アラートメール送信機能
ファイル:mailbody.ps1でメール送信に必要なPowerShellスクリプトを構成し、バッチファイル内では
「Powershell -command "%MailPs%"」
行で呼び出して使っています。
「mailbody.ps1」内はメール送信に必要な設定(Outlookのようなメールソフトに設定するような設定値)を変数に入れて、最後の行の
New-Object Net.Mail.MailMessage
でメールメッセージを生成し、
SMTPClient.Send($Mail)
で送信を実行しています。
メールはシンプルに、
こんな感じのメールが飛びます。
メール送信のPowerShellに関しては、もう少しいろいろやれそうな感じがしますので、時間があったらもうちょっと検証してみたいと思います。
たとえば、今回は1バッチ対して1つの.ps1ファイルになっていますが、これが汎用的に(別のバッチでも)使えると便利かなぁと思いました。