Тема: CMD/BAT: Асинхронный ICMP-сканер подсети
Довольно часто возникает необходимость выяснить "демографию" того или иного участка корпоративной сети - какие ip заняты, какие хосты живы, какие у хостов имена и т.п. Зачастую эти участки являются обособленными подсетями, не имеющими непосредственного контакта ни с интернетом, ни с собственно сетью предприятия (например, биржевые терминалы трейдеров в банке). А если еще ИБ запрещает посторонний софт...
В таких случаях, когда под рукой только консоль cmd и собственные ручки, на помощь приходит простенький цикл, который, к слову, здесь уже не раз обсуждался:
for /l %i in (1,1,254) do @ping -a -n 1 192.168.100.%iОднако, есть у этого решения досадные минусы: долго работает и выводит в не слишком удобном для просмотра и анализа виде.
Как бы сделать батник многопоточным, да еще чтоб данные сверстались в нужном формате?
Легко! Пинги запускаем асинхронно с помощью команды start. Результат каждого пинга перенаправляем в файл с именем пингуемого ip-адреса. Дожидаемся завершения всех пингов, считываем результирующие файлы, выкидываем из них всё лишнее и выводим:
@echo off
:: Запуск:
:: scan.cmd <subnet>
::
:: Параметры:
:: <subnet> - три первых октета ip-адреса (идентификатор подсети)
::
if "%1"=="" goto usage
:: Задаем сигнальные строки (отличаются в зависимости от локали)
echo | find "is" >nul || goto set_ru
:set_en
set STR1="Reply ["
set STR2=": bytes"
set TKNS=2,3
goto set_end
:set_ru
set STR1="Ответ ["
set STR2=": число"
set TKNS=4,5
:set_end
:: Создаем временную директорию
pushd %APPDATA%
md %1
cd %1
:: Полный пинг подсети (асинхронно)
echo * Залп из пингов. Не пугайтесь, в считанные секунды всё утихнет...
for /l %%i in (1,1,254) do start /b cmd /c ping -a -n 1 %1.%%i ^| findstr %STR1% > %1.%%i
:: Ожидание завершения всех пингов
echo * Ожидание завершения всех пингов (20 сек)...
ping -n 20 127.0.0.1 > nul
echo * Маленькое причесывание результата...
:: Зачистка безответных пингов
for %%i in (*) do find %STR2% <%%i >nul || del %%i
:: Причесывание оставшихся живых
for /f "tokens=%TKNS% delims=[] " %%i in ('for %%h in ^(*^) do @type %%h ^|find "["') do ren %%j "%%j %%i"
echo * Готово!
echo.
:: Вывод результата
::dir /b /o:d
::dir /b /o:n
:: Штатной числовой сортировки нет, поэтому мутим ея своими силами
for /l %%i in (1,1,254) do if exist %1.%%i (dir /b %1.%%i) else if exist "%1.%%i *" (dir /b "%1.%%i *")
:: Убираем за собой
echo Y | del * >nul
cd ..
rd %1
popd
exit /b
:usage
echo Использование: %~nx0 ^<маска^>
echo где ^<маска^> ~= N.N.N ^(e.g. 192.168.99^)
echo.
echo Описание: Сканирует подсеть класса C на предмет живых хостов.
exit /b
