Windowsのバッチと言うと既に枯れた技術の印象ですが、日々の運用や簡単な作業を自動化するものとして重宝されています。ミドルウェアに依存せず、どのWindows OS上でも動作し、さらには自動化することで日々の作業削減と人的ミスの予防も期待できます。そこで、今までの私の構築経験などから役に立ちそうなバッチ・スクリプトを備忘録的にいくつか紹介します。
注)エラー処理を省略しています。必要に応じてエラー処理を行ってください。
目次
監視運用に使えるバッチ
監視と言えば、エージェントを入れて監視サーバで集中管理することもできますが、1~2台のサーバを監視するために別途で専用の監視サーバを構築したり、監視用のアプリケーションを購入するのは現実的ではありません。バッチで、ある程度のことは実現可能なので、そのいくつかを紹介します。
注)Windowsタスクスケジューラなどで定期動作することを前提にしています。
プロセスの監視
動作中のプロセスをtasklistコマンドで監視して、特定のプロセスが見つからない場合にアクションを起こすことができます。下記は、SQL Serverのプロセスが見つからない場合に、Windowsイベントログにエラーを出すサンプルです。
1 2 3 4 5 6 7 8 9 |
REM 監視するプロセス名 set PROC=sqlserver.exe REM プロセス一覧から監視対象のプロセス名を探す tasklist | find "%PROC%">nul if not %ERRORLEVEL%==0 ( REM イベントログにエラーを出力する eventcreate /ID 100 /L APPLICATION /SO MaintenanceLog /T ERROR /D "%PROC%のプロセスが見つかりません。" ) |
サービスの監視
動作中のサービスプログラムをsc queryコマンドで監視して、「開始」状態になっていなければアクションを起こすことができます。
下記は、Internet Information Services(以下、IIS)のサービスが動作中でなければ、Windowsイベントログにエラーを出すサンプルです。
1 2 3 4 5 6 7 8 9 |
REM 監視するサービス名 set SVC=W3SVC REM サービスの動作状態を確認する sc query %SVC% | find "RUNNING">nul if not %ERRORLEVEL%==0 ( REM イベントログにエラーを出力する eventcreate /ID 100 /L APPLICATION /SO MaintenanceLog /T ERROR /D "サービス %SVC% の動作が確認できません。" ) |
メールの送信
監視結果をイベントログにエラーとして出している場合、異常の発見が遅れる可能性があります。監視対象のサーバ等からアラートを出す手段としては、メールが効果的です。メールの送信はバッチでは難しいため、VBScriptを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
'' '' ファイル名:sendmail.vbs '' Option Explicit On Error Resume Next Dim objMsg Set objMsg = CreateObject("CDO.Message") objMsg.From = "送信元メールアドレス" objMsg.To = "送信先メールアドレス" objMsg.Subject = "【警告】Server01 監視運用連絡" objMsg.TextBody = WScript.Arguments(0) objMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 objMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "SMTPサーバ" objMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = SMTPポート番号 objMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = true objMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = true objMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "認証ユーザ" objMsg.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "認証パスワード" objMsg.Configuration.Fields.Update objMsg.Send Set objMsg = Nothing |
上記VBScriptのファイルを作成し、バッチから下記の方法でスクリプトを呼び出してメールを送信することができます。
1 |
cscript //nologo sendmail.vbs "Server01でエラーが発生しました。詳しくはイベントログを確認してください。" |
これまでの「プロセスの監視」「サービスの監視」「メールの送信」のサンプルを合わせたものを下記に掲載します。プロセスとサービスの確認を行い、その結果をメールで送信するサンプルです。なお、メール送信のVBScriptは、バッチを実行する都度、バッチ内で作成しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
@echo off cd /d %~dp0 REM メール送信用メッセージ set MSG1= set MSG2= REM メールスクリプトの一時ファイル名 set VBSWF=sendmail_tmp.vbs REM 監視するプロセス名 set PROC=sqlserver.exe REM プロセス一覧から監視対象のプロセス名を探す tasklist | find "%PROC%">nul if %ERRORLEVEL%==0 ( set MSG1=プロセス監視:OK ) else ( set MSG1=プロセス監視:NG - プロセス %PROC% が見つかりません REM エラーをイベントログに出力する eventcreate /ID 100 /L APPLICATION /SO MaintenanceLog /T ERROR /D "%PROC% のプロセスが見つかりません。" ) REM 監視するサービス名 set SVC=W3SVC REM サービスの動作状態を確認する sc query %SVC% | find "RUNNING">nul if %ERRORLEVEL%==0 ( set MSG2=サービス監視:OK ) else ( set MSG2=サービス監視:NG - サービス %SVC% の動作が確認できません REM エラーをイベントログに出力する eventcreate /ID 100 /L APPLICATION /SO MaintenanceLog /T ERROR /D "サービス %SVC% の動作が確認できません。" ) REM メール送信用VBSの一時ファイルを作成する echo Option Explicit>%VBSWF% echo On Error Resume Next>>%VBSWF% echo Dim objMsg>>%VBSWF% echo Set objMsg = CreateObject(^"CDO.Message^")>>%VBSWF% echo objMsg.From = ^"auto_mail@tdi.co.jp^">>%VBSWF% echo objMsg.To = ^"user1234@tdi.co.jp^">>%VBSWF% echo objMsg.Subject = ^"【警告】%COMPUTERNAME% 監視運用連絡^">>%VBSWF% echo objMsg.TextBody = ^"%MSG1%^" ^& vbCrLf ^& ^"%MSG2%^">>%VBSWF% echo objMsg.Configuration.Fields.Item(^"http://schemas.microsoft.com/cdo/configuration/sendusing^") = ^2>>%VBSWF% echo objMsg.Configuration.Fields.Item(^"http://schemas.microsoft.com/cdo/configuration/smtpserver^") = ^"smtp.tdi.co.jp^">>%VBSWF% echo objMsg.Configuration.Fields.Item(^"http://schemas.microsoft.com/cdo/configuration/smtpserverport^") = 25>>%VBSWF% echo objMsg.Configuration.Fields.Update>>%VBSWF% echo objMsg.Send>>%VBSWF% echo Set objMsg = Nothing>>%VBSWF% REM VBSを実行してメールを送信する cscript //nologo %VBSWF% REM 一時ファイルを削除する del %VBSWF% /f REM バッチの実行をイベントログに残す eventcreate /ID 100 /L APPLICATION /SO MaintenanceLog /T INFORMATION /D "バッチ監視を実施しました。" exit /b 0 |
定期処理運用に使えるバッチ
運用で自動化しておきたいものに、古いファイルの削除や再起動などがあります。
注)Windowsタスクスケジューラなどで定期動作することを前提にしています。
更新日時による古いファイルの削除
IISのような日々ログが蓄積されるシステムの過去ログを削除する運用は多々あります。ファイルの更新日による過去ログの削除は、forfilesコマンドを使用することで簡単に行うことができます。下記は、IISのログファイルの更新日を確認して、現在より60日以上古いファイルを削除するサンプルです。
1 |
forfiles /P "C:\inetpub\logs\LogFiles\W3SVC1" /M *.log /C "cmd /c if @isdir==FALSE del /f @path" /D -60 |
ファイル名に入っている日付で古いファイルの削除
ファイル名に含まれる日付(例えば 20180607 がファイル名に入る)を元に古いファイルを削除する場合は、forfilesコマンドは使えません。ファイル名から日付を抜き出して削除対象となる日付と比較して削除する方法になります。下記は、IISのログファイルのファイル名に含まれる日付を抜き出して、現在より60日以上古い日付のファイルを削除するサンプルです。なお、日付の計算はバッチでは長くなるのでVBScriptを使って簡単に行っています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
REM 遅延環境変数を有効にする setlocal enabledelayedexpansion REM 何日前から削除するか指定(60で60日前) set DAY=60 REM 日付計算用のスクリプトを作成する echo WScript.Echo DateAdd("d",-%DAY%,Date())>delete_iislog_tmp.vbs REM スクリプトで削除する起点の日付を取得する for /f "tokens=1-3 delims=/-" %%A in ('cscript //nologo delete_iislog_tmp.vbs') do set targetdate=%%A%%B%%C REM 取得が終わったのでスクリプトを削除する del delete_iislog_tmp.vbs REM ファイルを列挙する for /f "tokens=1" %%C in ('dir "C:\inetpub\logs\LogFiles\W3SVC1" /b *.log') do ( REM ファイル名から文字位置固定で年月日を抜き出す set wdate=%%C set wdate=!wdate:~20,8! REM 年月日を比較して、起点の日付より前なら削除する if !wdate! leq %targetdate% del /f "C:\inetpub\logs\LogFiles\W3SVC1\%%C" ) |
サービス停止・開始
バックアップを行う際などに、サービスやプロセスの動作を停止したい場合があります。サービスを停止・開始したい場合は、netコマンドを使用します。(scコマンドもありますが、非同期でコマンドが実行されるため、サービスの停止を待ってくれる netコマンドを使用しています)
下記は、IISのサービスを停止して、何かの処理の後に起動するサンプルになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
REM 停止と開始を行うサービス名 set SVC=iisadmin REM サービスを停止する net stop %SVC% if not %ERRORLEVEL%==0 ( REM エラーをイベントログに出力する eventcreate /ID 100 /L APPLICATION /SO MaintenanceLog /T ERROR /D "サービス %SVC% の停止に失敗しました。" REM サービス停止できないので処理を終了する exit /b 1 ) REM バックアップなどの処理をここで行う REM サービスを開始する net start %SVC% if not %ERRORLEVEL%==0 ( REM エラーをイベントログに出力する eventcreate /ID 100 /L APPLICATION /SO MaintenanceLog /T ERROR /D "サービス %SVC% の開始に失敗しました。" ) |
再起動
システムの安定稼働やWindows Updateなど、定期的に再起動を行いたい場合は、shutdownコマンドを使用します。下記で、再起動を待ち時間無し(0秒)で開始するサンプルです。
1 2 |
REM システム(OS)を再起動する shutdown /r /t 0 |
その他の使えるかもしれないバッチ
運用シーンでは無いですが、作業する際などに使えるかもしれないバッチです。
ネットワーク設定の変更
「本番用と開発用」や「社内用とメンテナンス用」など異なるネットワーク環境で作業する際に、毎回ネットワーク設定を変更するのは手間がかかります。固定IPをネットワークの設定から変更するのはnetshコマンドを使用して、それぞれのネットワーク用のバッチを用意すればネットワークの切り替えも楽になります。
下記は、固定IPアドレス、サブネット、ゲートウェイ、DNSを変更するサンプルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
REM 設定するIPアドレス set localip=192.168.1.100 REM 設定するサブネットアドレス set subnet=255.255.255.0 REM 設定するゲートウェイアドレス set gateway=192.168.1.1 REM 設定するDNSサーバのアドレス set dns_pri=192.168.1.10 REM ネットワーク設定を行う netsh interface ip set address "ローカル エリア接続" static 192.168.1.100 255.255.255.0 192.168.1.1 REM DNSの設定を行う netsh interface ip set dnsservers "ローカル エリア接続" static 192.168.1.10 primary |
インターネットプロキシの設定
最近はモバイル端末を社外へ持ち出すような運用も増え、社内ネットワークや持ち出し環境ネットワークといった異なるネットワーク経路になることがあります。この際、不便なのがインターネットプロキシ設定です。インターネットプロキシ設定は、レジストリに情報が格納されていますので、regコマンドを使用して設定を変更します。
下記は、プロキシが無効の場合は所定の設定を有効にし、プロキシが有効な場合は無効にするサンプルです。(Internet Explorerやインターネット設定が開いている場合は一度閉じる必要があります)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
REM 現在のProxyの設定状況を確認する reg query "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable | find "0x0" if %ERRORLEVEL%==0 ( REM プロキシを有効にする reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings" /f /v ProxyEnable /t reg_dword /d 1 REM プロキシサーバのIPアドレスとポート番号を設定する(任意)※設定を変える必要が無い場合は、プロキシの有効化だけでも可 reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings" /f /v ProxyServer /t reg_sz /d プロキシサーバー:ポート番号 REM 例外を設定する(任意) ※設定を変える必要が無い場合は、プロキシの有効化だけでも可 reg add "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings" /f /v ProxyOverride /t reg_sz /d "localhost;172.16.*;192.168.*" ) else ( REM プロキシを無効にする reg add "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings" /f /v ProxyEnable /t reg_dword /d 0 ) |
Windows更新情報の取得
作業PCの確認や何か問題が起きた時の調査のために、Windowsのパッチが適用されているか確認することがあります。「インストールされた更新プログラム」から確認することもできますが、WMICコマンドを使うことで簡単に一覧保存できます。下記は、パッチのKB番号とインストール日時をCSV形式でファイルに出力するサンプルです。
1 |
WMIC qfe get hotfixid,InstalledOn /format:csv>Hotfix.csv |
下記は、知りたいKB番号だけ(例:KB2515325)を指定してインストールされているか確認するサンプルです。インストールされていれば、ホスト名、KB番号、インストール日が画面に表示され、インストールされていなければ何も表示されません。
1 |
WMIC qfe get hotfixid,InstalledOn /format:csv | find "KB2515325" |
別ユーザでのプログラム実行
バッチの自動化で難しいのが別ユーザでコマンドを実行することです。”別ユーザでコマンドを実行する”こと自体は、runasコマンドがありますが、ユーザのパスワード入力が必要になります。そこで、PowerShellを利用してユーザの入力なしに”別ユーザでコマンドの実行”を行う例を挙げます。下記は、あるバッチファイルを管理者(Administrator)で実行するサンプルです。
1 |
powershell Start-Process -FilePath cmd.exe -ArgumentList /C,test.bat -Credential (New-Object System.Management.Automation.PSCredential 'Administrator', (ConvertTo-SecureString 'password' -AsPlainText -Force)) |
最後に…
いくつかのバッチを紹介してきましたが如何でしたでしょうか。流行のRPAには及びませんが、バッチでできることは非常に多く、工夫次第ではWindows上のもっと色々なことが実現できます。もし興味を持たれましたら、「こんなこと自動化できたら良いな」というちょっとした思いをバッチで実現してみては如何でしょうか。
執筆者プロフィール
- 10年くらい研究・開発の経験を経た後に、複数のパッケージ製品の構築・サポート要員として活動する器用貧乏なエンジニア。
この執筆者の最新記事
- iDC&セキュリティ2023.05.02ディープラーニングを活用したアンチウイルス製品と従来型アンチウイルス製品を比べてみた
- ITコラム2018.08.24Windowsバッチの簡易な運用活用法