【bat】PSEXECを利用して特定セグメントのPING応答のあったIPへarpコマンドを実行させる。

【コマンド、ツールの概要】
・bat内で設定した変数をもとに対象セグメント(もどき。IPv4アドレス第4オクテットを探索)に対しpingを投げまくり、
 応答のあったIPアドレスにPSEXECで接続しarp-aを打たせることでネットワーク内のMACアドレスを確認しよう、というスクリプト
・bat内変数で処理の設定を行うため、読める人が管理して実行することが推奨←


【環境(使っている環境)】
条件は過去記事参照。


【コマンド例】

SETLOCAL ENABLEDELAYEDEXPANSION

SET TARSEG=192.168.60.
SET STARTIP=2
SET ENDIP=253
SET WAITTIME=30
SET COUNT=0
SET SEGNO=%TARSEG:~8,-1%
SET PINGRES=c:\temp\pingarp_seg%SEGNO%.txt
SET ARPRES=c:\temp\arp_result_seg%SEGNO%.txt

SET PSEUSER=[管理ユーザ名を括弧閉じとかせずに記載]
SET PSEPASS=[管理ユーザのパスワードを括弧閉じとかせずに記載]

ECHO.
ECHO 処理中は本画面をクリック等しないでください。
ECHO (万が一した場合は[ESC]にて復帰してください。その場合結果が出力されないことがあります。)

ECHO.
ECHO 対象セグメント:%TARSEG%
ECHO IP調査中。調査範囲:%STARTIP%%ENDIP% 応答猶予:%WAITTIME%ミリ秒
ECHO. > %PINGRES%
ECHO. > %ARPRES%

REM 疎通可能IPの特定が必要なので、pingを打ってレスポンスを記録
FOR /L %%A IN (%STARTIP%, 1, %ENDIP%) DO CALL :sub %%A

FOR /F "tokens=1-2*" %%a IN (%PINGRES%) DO (
	ECHO %%a%%b%%c | FIND "からの応答" > NUL
	IF !ERRORLEVEL! equ 0 (
		SET /a COUNT=!COUNT!+1
		SET TARGETIP!COUNT!=%%a
	)
)
ECHO.
ECHO 反応したIPは以下の %COUNT%つ です。この後各IPへPSEXECにて接続します。
FOR /L %%A IN (1, 1, %COUNT%) DO ECHO !TARGETIP%%A!
TIMEOUT /T 2

ECHO 反応のあったIP >> %ARPRES% 
FOR /L %%A IN (1, 1, %COUNT%) DO ECHO !TARGETIP%%A! >> %ARPRES%

REM リモートでネットワーク内IP×MAC一覧を取得。ping記録からレスポンスあったIPのうち最後のIPを利用。
FOR /L %%A IN (1, 1, %COUNT%) DO PSEXEC -u !TARGETIP%%A!\%PSEUSER% -p %PSEPASS% \\!TARGETIP%%A! cmd /c "arp -a" >> %ARPRES%

ECHO 出力しました。処理を終了します。
ECHO 出力ファイル:%ARPRES%
TIMEOUT /T 5
EXIT /B

:sub
PING %TARSEG%%1 -n 1 -w %WAITTIME% >> %PINGRES% 2>&1
(SET <NUL /p="%1 ")|

【使用方法】
・(念のため管理者権限で)ローカル実行します。(管理者権限無くても行けると思いますが、、。)
・出力ファイルが「PINGRES」「ARPRES」にそれぞれ出力されます。


【説明】
まずは変数の説明。

TARSEG 調査したいセグメント(第3オクテットまで指定)
STARTIP 調査したいセグメントの開始IP(第4オクテットの開始IP)
ENDIP 調査したいセグメントの開始IP(第4オクテットの終了IP)
WAITTIME PINGの待ち時間指定。250回のPINGをすべてデフォルト(4秒)近く待つと1000秒とかやってらんないので。)
COUNT ループ変数
SEGNO 第3オクテットの切り出し(社内的事情←)
PINGRES PINGの結果ログ
ARPRES PINGレスポンスのあったIP列挙とarpの結果を記載したログ
PSEUSER PSEXECで使う管理ユーザ(一つ)
PSEPASS PSEXECで使う管理ユーザのパスワード

諸々解説。

FOR /L %%A IN (%STARTIP%, 1, %ENDIP%) DO CALL :sub %%A

まずfor文で、指定したIP範囲内IPごとにsubルーチンを呼び出します。

PING %TARSEG%%1 -n 1 -w %WAITTIME% >> %PINGRES% 2>&1
(SET <NUL /p="%1 ")|

pingを対象IPに指定の待ち時間で打ちつつ、ログに出力します。
同時に、SET行で画面に処理中の数値(第4オクテットの番号)を表示します。
これをforで回すことで、プロンプト画面でビジュアル的に処理が進んでいることがわかります。
(画面に「2 3 4 5 ・・・」みたいに数字が並んでいきます)

FOR /F "tokens=1-2*" %%a IN (%PINGRES%) DO (
	ECHO %%a%%b%%c | FIND "からの応答" > NUL
	IF !ERRORLEVEL! equ 0 (
		SET /a COUNT=!COUNT!+1
		SET TARGETIP!COUNT!=%%a
	)
)

for /fを使い、PINGのログファイルをfindで一行ずつ検索します。
応答があったIPをTARGETIP!COUNT!変数に格納します。
要するにTARGETIPは疑似配列?みたいな感じになっています。
(正しく言おうとするならTARGETIP0、TARGETIP1とか個々の変数が作られる。batはここが独特だけど分かれば意外に便利でもある。)

FOR /L %%A IN (1, 1, %COUNT%) DO PSEXEC -u !TARGETIP%%A!\%PSEUSER% -p %PSEPASS% \\!TARGETIP%%A! cmd /c "arp -a" >> %ARPRES%

for文でPSEXECを対象IPに打っていき、結果をarp出力ファイルに出力します。
例えば1番目に192.168.0.2のIPが反応した場合、forループの中で実際は下記コマンドが実行されます。
(FOR /L 1 IN (1, 1, 1) DO )PSEXEC -u 192.168.0.2\[指定ユーザ名] -p [指定ユーザパス] \\192.168.0.2 cmd /c "arp -a" >> c:\temp\arp_result_seg0txt


【総評】
個人的にfor文のいい勉強になりました(ぇ
ENABLEDELAYEDEXPANSIONが有効活用されていますね←
pingログの出力が不要ならメモリ展開して2番目の処理とかが早くはなりそうですが、微々たるもんでしょう。。
PSEXECのarpの部分をmsgとかにするとか悪いこと考えたらいけませんね()
メモ帳ならログファイルを開いても一瞬しか権限奪わないと思うので、実行したあとログをみるのが当bat理解への早道かと思います。
 

【参考リンク】
.bat(バッチファイル)のforコマンド解説。 - Qiita