Avance.Lab

技術紹介

[PsTools] 紹介と使い方について

公開日:2023.04.28 更新日:2023.04.28

tag: ToolWindows

こんにちは。WwWです。

システム系の開発をしていると様々な問題が起こります。

そこで今回は実際に発生した事例と調査方法を紹介してみたいと思います。
原因の調査には『PsTools』というツールを使用しました。

PsTools とは

『PsTools』は、Microsoft社が提供している、Windowsで利用可能な数種類のコマンドラインツールが含まれている無料パッケージです。

パッケージとしてダウンロードできるPsToolsに含まれるツールは以下のとおりです。

ツール説明
PsExecプロセスをリモートで実行する
PsFileリモートで開かれたファイルを表示する
PsGetSidコンピューターまたはユーザーの SID を表示する
PsInfoシステムに関する情報を一覧表示する
PsPingネットワーク パフォーマンスを測定する
PsKillプロセスを名前またはプロセス ID で強制終了する
PsListプロセスに関する詳細情報の一覧
PsLoggedOnローカルおよびリソース共有を使用してログオンしているユーザーを確認します
(完全なソースが含まれています)
PsLogListイベント ログ レコードのダンプ
PsPasswdアカウント パスワードを変更する
PsServiceサービスの表示と制御
PsShutdownシャットダウンし、必要に応じてコンピューターを再起動します
PsSuspendプロセスを中断します
PsUptimeシステムが最後に再起動されてから実行されている時間を示します
(PsUptime の機能が PsInfo に組み込まれています)

※引用元※
PsTools (Microsoft社公式ページ)

事例:サーバのCPU使用率が100%近くになる現象が頻発するため解決したい

まず、何がCPU使用率を引き上げているのかを調査しなければなりません。

ここで、『PsTools』パッケージにある”PsList”コマンドを使用します。
公式ページの説明にもあるように、プロセスに関する詳細情報の一覧の取得ができるコマンドです。

ちなみにWindowsに標準搭載されているパフォーマンスモニターも”PsList”コマンドと同じような機能を持っていますが、
パフォーマンスモニターでは突発的にCPU使用率が跳ね上がる現象が発生した時に原因特定に至らなかったため、
今回は別の方法として”PsList”コマンドを使用しました。

それでは、”PsList”コマンドでプロセス毎のCPU使用率をチェックするバッチファイルを作成します。

フォルダ構成

test/
 
  PSTools/   ★ダウンロードしたPSTools.zipファイルを展開したディレクトリ
   pslist.exe (この中に”PsList”コマンドを入れておく)
 
  log/     ★ここにログが出力される
 
  cpu_check.bat

バッチファイル

@echo off
cd /d %~dp0

forfiles /D -2 /P .\log /M pslist*.txt /c "cmd /c del @file" 2>nul

set time_tmp=%time: =0%
set date_file=%date:~-10,4%%date:~-5,2%%date:~-2,2%%time_tmp:~0,2%%time_tmp:~3,2%%time_tmp:~6,2%

.\PSTools\pslist.exe /accepteula -s 3600 -r 1 > .\log\pslist_%computername%_%date_file%.txt

※logディレクトリはバッチファイルと同階層にあるため、「.\log」と指定しています

※PSToolsディレクトリもバッチファイルと同階層にあるため、「.\PSTools\pslist.exe」と指定しています

コード詳細説明

■ cd /d %~dp0

バッチファイルが置いてあるディレクトリに移動するコマンドです。

%~dp0 は、ファイル名を含むバッチファイルのフルパス(%0)からファイル名を除いたパスのことです。

 例)バッチファイルのフルパスが “D:\test\cpu_check.bat” の場合、
   %~dp0 の結果は “D:\test\” となります。

また、cd コマンドはディレクトリを移動するコマンドです。
別ドライブに移動する場合は /d オプションを使用します。

■ forfiles /D -2 /P .\log /M pslist*.txt /c "cmd /c del @file" 2>nul

forfiles は、指定した条件に該当するファイルに対して、指定した処理を実行するコマンドです。
今回は[“.\log\pslist*.txtファイル”の最終更新日から2日経過したログファイルを削除]する条件のコマンドになります。

また、削除対象のファイルがない場合、「エラー: 指定した検索条件でファイルが見つかりませんでした。」とエラーメッセージが表示されてしまうため、
末尾に 2>nul を付けることでエラーメッセージを非表示にしています。

forfilesの構文例:
forfiles /D -<日数> /P <パス名> /M <検索したいファイル名> /c <実行コマンド>

オプション説明
「/D」オプション指定された最終更新日からの日数を経過したファイルを対象とする
今回の /D -2 は、2日前以前のファイルを対象としている
「/P」オプション対象となるパスを指定する(デフォルトはカレントディレクトリ)
今回の /P .\log は、.\logディレクトリ下に対象のファイルがあることを指定している
「/M」オプション対象となるファイル名を指定する(ワイルドカード使用可能)
今回の /M pslist*.txt は、ファイル名がpslistから始まる.txtファイルを指定している
「/C」オプション対象のファイルに対して実行するコマンドを指定する
※注:コマンドはダブルクォーテーション[""]で囲む必要がある
今回の /c "cmd /c del @file" は、条件に合った対象のファイルを削除するコマンドになる

■ set time_tmp=%time: =0%
■ date_file=%date:~-10,4%%date:~-5,2%%date:~-2,2%%time_tmp:~0,2%%time_tmp:~3,2%%time_tmp:~6,2%

ここでは、結果を出力するログファイル名に使用するための”年月日時分秒”を抽出しています。

「date」は日付、「time」は時刻を取得することができます。

ただし、「time」において、時間が1桁の場合(0:00:00~9:59:59)、先頭に空白が入る仕様になっています。
 例)午前0時の場合:[ 0:00:00.00]
   ※緑色ハイライト部分が空白

そのため、%time: =0% で空白部分を「0」に置換しています。
 例)午前0時の場合:[ 0:00:00.00] → [00:00:00.00]となる

set time_tmp=%time: =0% では、置換後の結果を変数”time_tmp”にセットしています。

次に、「date」や「time」は、ファイル名に使用できない日付区切りの「/」と時刻区切りの「:」を含んでいるので、
%date:~-10,4%%date:~-5,2%%date:~-2,2%%time_tmp:~0,2%%time_tmp:~3,2%%time_tmp:~6,2% を実行することで
「/」や「:」を除いた”年月日時分秒”を抽出しています。
 例)date=2023/04/28、time=12:00:00.01の場合:抽出結果は[20230428120000]となる

set date_file=%date:~-10,4%%date:~-5,2%%date:~-2,2%%time_tmp:~0,2%%time_tmp:~3,2%%time_tmp:~6,2% では、
日付と時刻の抽出結果を変数”date_file”にセットしています。
この変数”date_file”は後のログ出力の箇所で使用します。

■ .\PSTools\pslist.exe /accepteula -s 3600 -r 1 > .\log\pslist_%computername%_%date_file%.txt

ここでは、”PsList”コマンドでCPU使用率を3600秒(1時間)の間、1秒間隔で取得し、ログファイルに出力する処理を実行します。

PsListの構文例:
pslist.exe /accepteula -s <実行秒数> -r <更新間隔>

オプション説明
「/accepteula」
オプション
ライセンス同意のダイアログウィンドウをスキップする
(ウィンドウを表示させない)
「-s」オプション実行する秒数
今回の -s 3600 は、”PsList”コマンドを3600秒実行することを指定している
「-r」オプション更新間隔(秒)
今回の -r 1 は、1秒間隔でCPU使用率の情報を取得することを指定している

> .\log\pslist_%computername%_%date_file%.txt は、実行結果表示を指定したファイルに出力しています。
ここでは、”PsList”コマンドの実行結果を、”コマンドを実行したPC名”(%computername%)と”年月日時分秒”(%date_file%)をファイル名に含めて出力しています。

 例)PC名:TEST-PC、実行日時:2023/04/28 12:00:00 の場合、
   出力ファイル名は[pslist_TEST-PC_20230428120000.txt]となる

実行方法

■ 手動実行

手動で実行する場合は、作成したバッチファイルをダブルクリックします。

実行開始するとコマンドプロンプトウィンドウが起動するので、終了する場合はウィンドウ上で[Ctrl]+[C]キーを押してください。

■ 自動実行

自動で実行する場合は、タスクスケジューラを使用します。

長時間定期実行をしてサーバを監視したい場合は、こちらを推奨します。

例えば、「毎日0:00に起動、1時間ごとに繰り返す」条件のトリガーでバッチファイルを実行するように設定すれば、
自動で毎日1時間ごとに”PsList”コマンドで情報を収集してログファイルに出力することができます。
バッチファイルにはログファイルの削除機能もあるため、ログファイルの管理も問題ありません。

トリガー:「毎日0:00に起動、1時間ごとに繰り返す」
※1時間ごとにログ削除機能と”PsList”コマンド情報ログ出力機能が実行される
作成したバッチファイルのパスを指定         

実行結果

3600秒(1時間)の間、1秒間隔でプロセス毎の情報を出力してくれます。
CPU使用率は「CPU」列に出力されます。

”PsList”コマンド実行中に問題が起きた場合、異常発生時刻付近のログを確認してみましょう。

例として、サーバ異常が 2023/04/28 12:49:52 に発生したとします。

  • 異常発生時の”PsList”コマンドログ例
異常発生時の”PsList”コマンドログ例
ログ時刻ログ内容
2023/04/28 12:49:50

2023/04/28 12:49:51
CPUを確認すると、Idle(CPUを使わない空のプロセス)プロセスが一番高いため問題なし。
2023/04/28 12:49:52
(異常発生時刻)
Application_aaaプロセスのCPUが90%となってしまっています。
IdleプロセスのCPUが低いことから、CPUの空きがほぼないことがわかります。
これらのことより、Application_aaaプロセスのCPU使用率が異常に高くなったことでサーバに高負荷がかり、異常が発生したと考えられます。
2023/04/28 12:49:53

2023/04/28 12:49:54
依然としてApplication_aaaプロセスのCPUが異常に高いままです。
2023/04/28 12:49:55

2023/04/28 12:49:56
Application_aaaプロセスのCPUが下がり、IdleプロセスのCPUが上がりました。
ここで自然復旧したようです。

このように”PsList”コマンドを一定間隔で取得してログに保存するようにし、サーバ運用中に動作が重くなった時にログを確認して、
どのプロセスのCPUが高まっていたか判明すれば、何が悪さをしていたが明らかにすることができます。

今回の例では、Application_aaaプロセスが原因だったことがログから判明しました。

原因が分かれば、対象アプリの改修や運用方法など対応策を検討することができます。

まとめ

いかがでしたでしょうか。

今回は”PsList”コマンドを紹介しましたが、『Pstools』パッケージには他にも様々なコマンドがありますので、
興味がある人は是非調べて使ってみてください。

機会がありましたら今度他のコマンドも紹介してみたいと思います。

WwW

ハードを設定したり、Web開発したり、ラズパイ触ったり。

青色が好き。

関連記事