🕒

バッチファイルでリモートサーバの情報を取得してCSVに落とす

2024/01/12に公開

何が起こったのか

社内サーバ(Windows)上で動いているプロセスがクラッシュし、障害が発生してしまった。
どうやらメモリリークが発生していたようで、プロセスのメモリ消費量を継続的に監視し、上限に近づいたらプロセスを手動で再起動する必要性が生じた。
(めんどくさいが、プログラムの修正パッチがリリースされるまでの繋ぎの運用)

しかし、ずっとサーバの画面のタスクマネージャとにらめっこしているわけにもいかないし
かといって資産管理システム等が入っているわけでない。
加えて、できればメモリ消費量の増加傾向についても記録し、どのタイミングで異常増加しているのか調査できればと思った。

そこで、例によってバッチファイルの力を借りることにした。

環境

  • Windows 10 Pro Version 19041 (クライアント)
  • Windows Server 2019 Datacenter 17763 (サーバ)

実例

サーバのIPアドレスは「192.168.101.72」で、クライアントから情報を取得しに行くものとする。

プロセスのメモリ容量の監視

プロセスのステータスは、tasklistコマンドで確認ができる。
また、リモートコンピュータの情報も取得が可能。

tasklistの例
PS C:\Users\kumasun> tasklist /S 192.168.101.72 /U 192.168.101.72\administrator /P ADMIN_PASSWORD /fi "imagename eq SomeService.exe"

イメージ名                     PID セッション名     セッション# メモリ使用量
========================= ======== ================ =========== ============
SomeService.exe              14180                            0  2,360,584 K
PS C:\Users\kumasun>

サーバ上のSomeService.exeのステータスについて取得を行った例である。
コマンドライン引数でサーバのIPアドレスとユーザ名・パスワードを指定し、イメージ名で絞り込みをかけて表示したものである。

tasklistコマンドの引数に出力フォーマットを指定できる/FOオプションと、ヘッダを出力しない/NHスイッチがあり、ヘッダ出力なし・出力フォーマットとして「CSV」を指定した場合の出力例については下記の通りである。

tasklistの例(CSV)
PS C:\Users\kumasun> tasklist /FO CSV /NH /S 92.168.101.72 /U 192.168.101.72\administrator /P ADMIN_PASSWORD /fi "imagename eq SomeService.exe"
"SomeService.exe","14180","","0","2,358,632 K"
PS C:\Users\kumasun>

これに日付時刻をくっつけてファイルに書き出せば完成だ。

check_task.bat
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

SET CURDIR=%~dp0

REM FOR /F "tokens=*" %%F IN ('tasklist /FO CSV /NH /S 192.168.101.72 /U 192.168.101.72\administrator /P ADMIN_PASSWORD /fi "imagename eq SomeService.exe"') DO SET USAGE=%%F

ECHO "%Date%","%Time%",%USAGE% >> "%CURDIR%MemoryUsage_SomeService.exe.log"

EXIT /B

上記例は、バッチファイルと同階層に「MemoryUsage_SomeService.exe.log」というファイルにデータを追記していくものである。

このバッチファイルをWindows標準のタスクスケジューラで定期的に実行するように仕掛ける。

そして出来上がったファイルがこれだ。

MemoryUsage_SomeService.exe.log
(前略)

"2023/11/07","17:30:00.27","SomeService.exe","13692","","0","977,616 K" 
"2023/11/07","17:45:00.29","SomeService.exe","13692","","0","975,644 K" 
"2023/11/07","18:00:00.29","SomeService.exe","13692","","0","979,908 K" 
"2023/11/07","18:15:00.33","SomeService.exe","13692","","0","986,636 K" 
"2023/11/07","18:30:00.47","SomeService.exe","13692","","0","986,952 K" 

(後略)

あとはこれをExcel等にインポートし、適宜体裁を整えればよい。

わたしの環境では、メモリ使用量と日付時刻を用いて将来予測(FORCAST関数)を行い
プロセスを再起動するタイミングをざっくり決めている。

サーバの物理メモリの状況を監視

ここまで見えるのであれば、物理メモリの空き容量についても知りたいと思うのが情シスの心情というもの(?) だ。

しかし、前述のtasilistコマンドはあくまでも動作しているプロセスの状況を知るためのものであり、全体のメモリの状況を把握できるようなものではない。

Windowsにシステム構成情報を取得できるsysteminfoコマンドが標準で入っており
出力結果にメモリの状況も含まれているようなので、これを利用することにした。

systeminfoコマンド出力例
PS C:\Users\kumasun> systeminfo

ホスト名:               shirokuma
OS 名:                  Microsoft Windows 10 Pro
OS バージョン:          10.0.19041 N/A ビルド 19041

(中略)

入力ロケール:           ja;日本語
タイム ゾーン:          (UTC+09:00) 大阪、札幌、東京
物理メモリの合計:       7,904 MB
利用できる物理メモリ:   3,459 MB
仮想メモリ: 最大サイズ: 20,192 MB
仮想メモリ: 利用可能:   13,615 MB
仮想メモリ: 使用中:     6,577 MB

(以下略)

物理メモリや仮想メモリの情報はここに載ってくる。
また、tasklistコマンドと同様に、引数でリモートコンピュータの情報も取れてくる。

systeminfoコマンド出力例(リモート)
PS C:\Users\kumasun> systeminfo /S 192.168.101.72 /U 192.168.101.72\administrator /P ADMIN_PASSWORD

ホスト名:               SERVER
OS 名:                  Microsoft Windows Server 2019 Datacenter
OS バージョン:          10.0.17763 N/A ビルド 17763

(中略)

システム ロケール:      ja;日本語
入力ロケール:           ja;日本語
タイム ゾーン:          (UTC+09:00) 大阪、札幌、東京
物理メモリの合計:       49,151 MB
利用できる物理メモリ:   12,935 MB
仮想メモリ: 最大サイズ: 78,847 MB
仮想メモリ: 利用可能:   41,808 MB
仮想メモリ: 使用中:     37,039 MB

(以下略)

systeminfoコマンドを実際に流してみると分かるが、情報取得に数秒~数十秒かかり
複数項目を取得するとき、毎回もコマンドを流すと待ち時間が発生する上、サーバにいらぬ負荷をかけてしまう可能性がある。
バッチ化するにあたり、これも考慮に入れる必要がある。

check_memory.bat
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

SET CURDIR=%~dp0

systeminfo /S 192.168.101.72 /U 192.168.101.72\administrator /P ADMIN_PASSWORD > "%CURDIR%systeminfo.tmp"

FOR /F "tokens=2 delims=:" %%F IN ('find "物理メモリの合計" "!CURDIR!systeminfo.tmp"') DO SET TOTAL=%%F
FOR /F "tokens=2 delims=:" %%F IN ('find "利用できる物理メモリ" "!CURDIR!systeminfo.tmp"') DO SET AVAIL=%%F

DEL "%CURDIR%systeminfo.tmp"

ECHO "%Date%","%Time%","%TOTAL%","%AVAIL%" >> "%CURDIR%Memory_SomeService.exe.log"

EXIT /B

上記例は、バッチファイルと同階層に「systeminfo.tmp」という一時ファイルを作成し、systeminfoの情報をプール。
そのファイルから指定された文言を含む行を抽出し、セミコロンで分割してデータだけ抽出。
そのデータを同階層の「Memory_SomeService.exe.log」というファイルにデータを追記していくものである。

同様に、これをWindows標準のタスクスケジューラで定期的に実行するように仕掛ける。

そして出来上がったファイルがこれだ。

Memory_SomeService.exe.log
(前略)

"2024/01/12","11:15:05.03","       49,151 MB","   12,969 MB"
"2024/01/12","11:30:04.08","       49,151 MB","   12,970 MB"
"2024/01/12","11:45:05.05","       49,151 MB","   12,969 MB"

(後略)

同様にExcelに取り込んで傾向を観察することができるようになった。
また、前述のtasklistを用いたバッチファイルに組み込んで同時に出力させることもできる。

原理的には仮想メモリの状況も取ってこれるが、セミコロンが2つ入っているのでFORのパラメータ調整が必要だろうと考えられる。(試してない)

おわりに

転職先募集中です

Discussion