Это библиотека скриптов, которые время от времени приходится писать, чтобы выполнить какие-то утилитарные задачи.
Некоторые оказываются достаточно жизнеспособные, для того, чтобы быть опубликованными.
Большинство скриптов, пишутся для себя, чтобы автоматизировать какие-то задачи, а не выполнять их раз за разом, подобно роботу, поэтому они редко отличаются красотой исполнения, форматированием, комментариями. И ценность их остается в рамках решаемой ими задачи.
Мне же, интересно, когда подворачивается наобходимость написать скрипт для себя или для сторонней компании в рамках какого нибудь проекта, интересно сделать так, чтобы скрипт был законченным, как программа. Встроенная помощь, указание командной строки, проверка параметров, то есть, все чтобы скриптом мог пользоваться не только я. Некоторые, на мой взгляд, вполне могут быть автономны и использованы за рамками тех проектов, для которых они писались.

Так что милости прошу, в мою библиотеку.
НазваниеИстория и описание
Active Directory Tree Walker

ADScan3.cmd

Часто приходится сталкиваться с AD каталогами. Делать какие-то утилитарные вещи, например, обнаруживать изменения, портировать, синхронизировать. Разные задачи.
В связи с этим написался скрипт, который обходит дерево каталога и выводит все пользовательские записи, которые находит на своем пути от самого глубокого до верха.


Параметры запуска:
ADScan3.cmd "[OU=OUnit],DC=Your_domain,DC=Local"
В командной строке вы указываете домен или OU от которого должен начаться обход дерева.
Алгоритм работы рекурсивный:
Скрипт рекурсивно вызывает сам себя, передавая в первом параметре, необходимый для сканирования полный контекст, а во втором параметре передается тот-же контекст, но относительный.
В скрипте реализован механизм исключения. Для этого надо создать файл с таким-же названием, как у этого скрипта, но с расширением .excpt, то есть ADScan3.excpt и прописать туда контекст, который необходимо исключить из обхода в следующем формате:
"-OU=ExceptedOU1,DC=Your_domain,DC=local"
"-OU=ExceptedOU2,DC=Your_domain,DC=local"

Двойные кавычки обязательны, так же как и минус.



Все действия, которые вы хотите сделать надо делать внутри этой команды:
for /f "usebackq delims=@ tokens=1" %%b in (`dsquery user  -o upn -scope onelevel "%~1"`) do (
	echo %~2%%~b
)
rem End of "for /f "usebackq delims=@ tokens=1" %%b in "
Команда: "echo %~2%%~b", демонстрирует имеющиеся у вас параметры для работы:

%1Текущий полный контекст
%2Текущий относительный контекст
%%bПеребираемый объект типа User в текущем контексте

Login, IP, Machine Generator

GenLogin_Machine_Ip2.cmd

Для системы учета трафика потребовалось получать IP адреса и Netbios имена машин привязанных к AD логинам пользователя.

Для этой задачи был написан этот скрипт, который в качестве параметра в командной строке, принимает адрес сервера, с которого он считывает нужную ему инфрмацию.
Так как акт авторизации машины в Security Log'е, происходит довольно часто, то в скрипте реализована защита от дублирования строк.

findstr /c:"%%a" %1>nul
if !errorlevel! EQU 1 echo %%a >>%1
Использование этой конструкции накладывает необходимость запуска командного процессора в режиме "delayed environment variable expansion", включающимся ключем "/v:on".
Основная часть - это проверки на возможность корректной отработки скрипта.


Для работы вам понадобится программа ELogDmp.Exe из resource kit for windows 2000.
Не тестировал, но теоретически, должна работать с DumpEL.exe запущенного с командной строкой "-с", чтобы в качестве разделителя использовались запятые, как это реализовано в elogdmp.
Login.cmd Возникла задача, запуска скриптов в момент запуска рабочей станции, логина, логаута и выключения рабочей станции. Соотвественно, некоторые задачи надо было запускать переодически, а некоторые один раз для рабочей станции и(или) для пользователя.
Единственный способ заставить рабочую станцию отработать скрипт: это прописать его в групповой политике для пользователя или для компьютера. Но этот скрипт будет исполняться постоянно, находиться он будет в неудобном месте, отчета об отработке он не предоставит и при наличии большого разнообразия выполняемых задач, возникает путаница, в которой не помогает ни документирование, ни GPMC.
Но самое главное - это коммулятивный запуск необходимых команд на конкретной рабочей станции. Групповая политика подобной избирательности не допускает.

Так родилась идея запуска одного скрипта, который сам бы разбирался, что и где запускать. А для администратора, было бы просто обозрев один два файла, мгновенно понять, что, где, при каких условиях запустится и отработает. Также и с отчетами, отчеты можно отправлять по почте, а можно сохранять в специализированной папке, для последующего разбора и анализа. Опять-же все централизованно и в один, два взгляда.
У "Login.Cmd" есть два режима работы, Once и Repeat и два подрежима для Mode: Machine и User.
Once и Repeat - указывают на файлы для исполнения, а Login.Cmd, выбирая от туда строки, относящиеся для заданного подрежима, последовательно их выполняет.

Подрежимы ([Mode=[Machine] | [User]):
Machine - в этом подрежиме проверка происходит для текущей рабочей станции. Проверке подлежит домен и имя рабочей станции, имя текущего пользователя игнорируется.
User - в этом подрежиме проверка происходит для текущего пользователя. Соответственно, проверке подлежит домен и логин текущего пользователя, имя рабочей станции игнорируется.
Once=[OnceFile.txt] - управляющий файл со списком команд, которые требуется запустить один раз для текущего подрежима.
Repeat=[RepeatFile.txt] - управляющий файл со списком команд, которые требуется запускать каждый раз при запуске Login.Cmd


Теперь подробно:
Чтобы Once работал, требуется где-то запоминать выполненные команды, а если они изменились, то не игнорировать их. Поэтому для работы Once требуется еще флаговый файл, куда будет заноситься информация о выполненных командах и машинах или пользователях, для которых это все успело выполниться.
Флаговый файл может создаваться автоматически там же, где находится управляющий файл, что обычно быть не должно, туда должен иметь права только администратор, либо его можно задать параметром Markers, где указать полный путь до файла, в который будет добавляться информация о выполненных командах. Не забывайте про права на запись, а если файла нет, то и на создание.
Для Repeat такая конструкция не требуется.
В Login.Cmd реализована возможность отсылки результатов работы всех выполненных команд на почту. Соответсвенно, все параметры указываются через командную строку.
Это:
Все параметры должны быть указаны. Пропуск любого из них приводит к невозможности отправки почты
MailFromMailС какого почтового адреса будет присылаться письмо. (Например: Robot@mydomain.ru)
MailFromNameОт кого будет присылаться письмо. (Например:Informer)
MailToКому будет отсылаться почтовый отчет. (Например: admin@mydomain.ru)
MailServerСервер SMTP, через который будет отправляться почта.
MailLoginЛогин на SMTP сервер, чтобы отправить почту
MailPassПароль к логину на SMTP сервер, чтобы отправить почту
MailFileLogin.Cmd подробно протоколирует свои действия, все это сохраняется в указанный файл. Он не удаляется после отправки. Сделано это умышленно, чтобы иметь возможность хранить данные, за период более, одной сессии.
Важно: Не указывайте файл со статичным названием, потому что одновременая запись невозможна. Используйте подстановки, например: MailFor%computername%_%username%.txt. И конечно, не забывайте про права на запись.
ICONVКлюч одновременно активирует ковертацию из CP866 в CP1251 и указывает, где следут искать утилиту iconv.exe

Параметры запуска могут быть указаны в произвольном порядке.
Хорошим правилом, будет запуск Login.Cmd с параметрами из пакетного файла, который уже выполнит необходимые манипуляции с оставшимся после отработки Login.Cmd файлом отчета. Да и вообще удобно, при отладке и понимании. И уже этот файл прописывать в скриптах групповой политики.

Пример:
===UserLogin.cmd===

call \\Srv\SrvLogin\login.cmd Mode=User Once="\\Srv\SrvLogin\Control\LoginOnce.txt" Period="\\Srv\SrvLogin\control\LoginRepeat.txt" Markers="\\Srv\SrvLogin\Control\Markers\LoginMarkOnce.txt" MailFile="\\Srv\SrvLogin\OutReports\LoginM%Computername%.txt" MailFromName="%Computername%@mydomain.ru" MailFromMail="null@mydomain.ru" MailTo="Admin@mydomain.ru" MailServer="mail.mydomain.ru" MailPass="MegaPassword" MailLogin="RobotInformer@mydomain.ru"
del "\\Srv\SrvLogin\OutReports\LoginM%Computername%.txt"

===UserLogin.cmd===

Mode- задает режим работы.
User - пользовательский. Это указывает скрипту, что надо выделять строки имеющие параметр USR и проверять целевой домен и имя пользователя с тем, что указано.
Machine - Машинный. Указывает скрипту, что надо выделять строки имеющие параметр WKS и проверять целевой домен и имя рабочей станции с тем, что указано.
Once- указывает полный путь до управляющего файла с единожды исполняемыми командами
Period- указывает полный путь до управляющего файла с переодически исполняемыми командами
Markers- указывает полный путь до файла, где будут храниться отметки об исполненных командах
MailFile- полный путь до файла, в который будет сохраняться отчет об исполнении
MailFromName, MailFromMail,
MailTo, MailServer,
MailPass, MailLogin
- задаются параметры работы с почтовым сервером.
ICONV- если указан этот параметр, то весь вывод будет преобразовываться из кодовой страницы 866 в кодовую страницу 1251.
    полный вызов команды iconv выглядит следующим образом: "iconv -c -s -f cp866 -t cp1251"

Теперь о форматах управляющих файлов. Они одинаковые.
Rem - это ремарка. Когда она встречается в начале строки, строка пропускается. После Rem может быть все, что угодно.
Пример управляющих строк выглядит так:
Ver:002 12:33:05:09:2008 NoLog WKS:* notepad.exe c:\123.txt
Ver:002 12:33:05:09:2008 NoLog WKS:MsHome\GreenWorkstation notepad.exe c:\123.txt
Ver:001 14:32:05:09:2008 Log USR:MsHome\GREEN notepad.exe "c:\space delimited folder\123.txt"
Ver:Любое число. Вы меняете версию и эта строка выполниться один раз для режима Once, запомнится и больше выполнятся не будет.
Для режима Repeat она игнорируется.
12:33:05:09:2008Временная метка строки. Нигде в проверках не участвует, сделано для того, чтобы понимать, когда возникла необходимость добавить эту программу на выполнение. Соответственно, нет и жесткого формата, главное, чтобы разделителем было ':', а как вы организуете запись даты и времени, это ваше право. Я использую такой формат: час:мин:число:месяц:год.
Log или NoLogУказывает скрипту протоколировать или нет работу программы. Если указано NoLog, то в протокол будет добавлена строка с уведомлением о запрете протоколирования.
Если указано Log, то в файл отчета будет перенаправлено основное устройство вывода(StdOut) и основное устройство вывода ошибок(StdErr).
WKS или USRУказывается для какого подрежима предназначена строка.
Cоответветсвенно, для WKS указывается имя рабочей станции в домене для которой необходимо выполнить программу, а для USR: доменное имя пользователя.
Звездочка означает, что привязка отсутствует.
notepad.exe c:\123.txtЗдесь указывается то, что требуется запустить. Это послений параметр, он никак не лимитирован.

Чтобы упростить начало работы с Login.Cmd, его можно запустить с параметром GenExampleFiles.
В результате, будут созданы файлы с примерами, рекомендуемая структура папок и файл "SetRights.Cmd", который задаст необходимые права, для созданной структуры.

Важно: Отправка почты работает при помощи утилиты blat. Скрипт ожидает ее обнаружить в папке Tools, находящейся там же, где находится он сам.

Password Generator

Gen.Rnd.v3.cmd

Генерирует случайную последовательность символов и цифр в формате: ABCDEF$1234
6 буквы, знак доллара, 4 цифры.
Можно использовать, например, для генерации паролей.
Берется время и выбираются числа из рандомизирующей таблицы.
В качестве таблицы используется первые 8 тысяч чисел после запятой, числа Пи. Так получается число после знака $.
Потом берется вновь время и по иному алгоритму, но с применением таблицы получается 12ти значное число, которое разбиваясь по два числа преобразуется в соответствии с заданным алфавитом в буквенную последовательность.
Разделяется знаком доллара и выводится на экран.

Статистические характеристики хреновые, но
на 1000 комбинаций (последовательных запусков) 1 коллизия:
Как проверять:
Cоздаете .cmd файл с таким содержимым:
for /l %%a in (1,1,2048) do call gen.rnd.v3.cmd >>gen.rnd.v3.test.txt 2>>&1
echo Testing...
for /f "usebackq tokens=1" %%a in ("gen.rnd.v3.test.txt") do for /f "usebackq delims=: tokens=1,2" %%b in (`find /i /c "%%a" "gen.rnd.v3.test.txt"`) do if not %%c EQU 1 echo Collision detected for: "%%a"
.
Сохраняете и запускаете его, помня, что количество обнаруженных коллизий в 2 раза меньше. Так как одна и та же строка будет обнаружена командой Find 2 раза в первый и во второй раз.

Back Date

Yaer2.cmd

При написании систем бекапа время от времени требуется, чтобы цикличность архива была произвольно задаваемой, для этого необходимо точно определять дату отстоящую от текущей на необходимое количество дней назад.
Данный скрипт реализует эту задачу.
Алгоритм написан "в лоб", отматывая указанное количество дней назад от текущей даты, хотя он и справляется с задачами, типа получить дату отстоящую на "2 222 222" от 15 декабря 2009, которая равна 20.9.-4075, но времени на это у него уходит много, хотя это 185185 итераций.

Логика работы:



%CurrDate% инициализируется текущей датой.
Определяем 3 таблицы, две нужные и одну не нужную:
DateHY - перечисляем количество дней для всех двенадцати месяцев вискосного года, обрамляя их "00" и "99"
DateNY - перечисляем количество дней для всех двенадцати месяцев обычного года, обрамляя их "00" и "99"
DateTest - перечисляем двухзначные названия для всех двенадцати месяцев года, обрамляя их "00" и "99"
После чего входим в большой цикл начинающийся OnStart
Далее дата разбирается на день, месяц, год готовые для математических операций и определение високосного года с инициализацией переменной "DayTable" значениями соотвествующей таблицы.

После этого начинается лобовое отматывание помесячных дней из заданного количества (if %Var_X% GEQ %CurrMDays% (....)), пока оно не станет меньше количества дней текущего месяца, уменьшая счетчик и указатель
%CX% на 2.
Выборка нового значения из таблицы производится следующей операцией:%Vatiable:~Start,Length% (Пример: >echo %date:~0,5%)
Так как у меня производится выборка по переменной %CX%, то чтобы избежать ошибки интерпретирования адресации двухбуквенного "элемента" таблицы (set CurrMDays=%DayTable:~%CX%,2%), который приводит к ошибке интерпретации, пришлось прибегнуть к альтернативной адресации, которая работает только в режиме setlocal enabledelayedexpansion, а именно адресации через восклицательный знак: set CurrMDays=!DayTable:~%CX%,2!

Последовательно вычитая (set /a Var_X=%Var_X% - %CurrMDays%) из заданных дней дни месяцев и время от времени, проверяя на окончание года (if !CX! equ 0), чтобы установить новый, в смысле старый, год текущим(set CurrDate=31.12.!CDateY!) и отдать управление на логику выяснения его високосности, скрипт отматывает настоящее в прошлое на указанное количество дней.

По исчерпанию введеных дней, вычисляем ожидаемый день, вычитая их из текущего месяца (set /a EstimatedDay=%CurrMDays% - %Var_X%) и вычисляя текущий месяц из текущего значения указателя в таблице (set /a CX=%CX%/2+1), а +1 необходим потому, что указатель всегда указывает на следующий месяц, значение дней которого должно быть взято на следующей итерации работы основного цикла (if %Var_X% GEQ %CurrMDays% (....)) (именно по этой причине необходимо было введение "00" в таблицу, чтобы избежать отрицательного значения %CX% в set CurrMDays=!DayTable:~%CX%,2!, который в случае отрицательного значения %CX% приводит к сбою в работе скрипта.)

NTP Stratums Tester

TestNTPStratums.cmd

Скрипт написан для выяснения группы наиболее близких и быстрых NTP серверов точного времени. Так как хорошей практикой является работа со стратумами 2 уровня (с 1 уровня рекомендуется брать только стратумам 2го уровня), то соответственно необходимо знать какие сервера быстрые, близко расположенные и на каких направлениях у них имеются проблемы с прохождением пакетов.
Все это сводится в таблицу и выводится в несортированном и сортированном виде.

Для работы этого скрипта потребуется две freeware программы командной строки:

FTrace - программа командной строки трассирующая маршрут до цели, выбрана за адекватный вывод, который не сводит с ума логику работы кардинально меняющимся числом выходных параметров в случае ошибок.
Ftrace:234ms 220ms 251ms 10.30.0.1694 параметра
Ftrace:331ms * * 66.185.150.304 параметра
Tracert: 135 ms 118 ms 158 ms 10.30.0.1697 параметров
Tracert: * * * Request timed out.4 параметра


Вторая программма это утилита командной строки, работающая с NTP сервером. На основе ее вывода можно выяснить отвечает ли NTP сервер или он только заявлен в таблице, включен, но не отвечает на запросы.

Cmdtime 3 - программа командной строки способная опрашивать и синхронизировать локальное время компьютера по показаниям NTP сервера точного времени.
За списком NTP серверов можно сходить по адресу: http://support.ntp.org/bin/view/Servers/StratumTwoTimeServers
Выделить таблицу, скопировать и сохранить в txt файл в кодировке ASCII. (по умолчанию)

После чего запустить скрипт, указав в командной строке имя файла со скопированной таблицей. На выходе получится два файла с суффиксами "_Unsorted" и "_SortedByErrors". Основная польза во втором файле, где наиболее безошибочные и быстрые хосты, прошедшие тестирование, находятся в верхних строчках.
Впрочем, файлы можно загрузить в Softkey:Excel или его аналог OpenOffice: Calc и обрабатывать их как заблагорассудится.

Отсюда одной упаковкой можно скачать все необходимые утилиты и скрипт со списком вторичных NTP серверов.

Работа скрипта выглядит примерно так:

NTP Tester.
============
Get list from command line and produce results in format:  Status, Trace errors, Hops, Average Time, HostName.
List can be obtained from http://support.ntp.org/bin/view/Servers/StratumTwoTimeServers
Table must be saved in txt file.

Status, Trace errors, Hops, Average Time, HostName
--------------------------------------------------------
Passed, 0000, 0014, 0448, ntp.grid.am
Passed, 0000, 0017, 0371, ntp.adc.am
Failed, 0009, 0023, 0346, ntp.ragingfist.net
Skipped: Zero hops for "maroochydore.time.flexi4site.net"
Passed, 0000, 0011, 0238, ntp1.tpg.com.au
.
.
Ping monitor

FPing_Monitor.Cmd

URL monitor

URL_Monitor.Cmd


FPing_Monitor Бывает, возникает необходимость наблюдать, как долго и в каком состоянии и когда находился хост.
Найти такую утилиту, которая вела бы протокол довольно сложно, обычно - это часть каких то больших мониторинговых систем диагностики сети.
Найти что-то простенькое, не вешающее собственные драйверы и не требующую развернутую SQL базу данных, не просто. Лично мне такие не известны.
Классический пинг дает только возможность уяснения состояния на текущий момент.
Но не покажет динамику подъемов и падений хоста, например что хост простоял 10 минут, потом не отвечал 2 минуты и поднялся вновь на 12 минут, после чего опять упал на 7 минут.
Чтобы подобную информацию увидеть и написан этот скрипт.

Ограничения:
* Максимальное измеряемое время в миллисекундах up/down тайма - сутки.
Ограничение происходит из-за того, что учитывается только время начала и окончания замера. И поэтому 1:12 20 января 2010 на 2 минуты больше 1:10 03 октября 2010.
Тем не менее, выводимая информация во время отчета в режиме CSV, показывает актуальную дату и время изменения состояния.
* Скрипт написан для внешней утилиты fping, у нее почеловечески реализовано возвращение кода возврата, по которому можно понять, что случилось, в отличии от штатного Windows XP ping'а.
По умолчанию, скрипт надеется найти утилиту в папке Tools рядом с собой.

Пример работы:


>fping_monitor.cmd 10.17.22.33 03.10.2010-02:38 |findstr /c:CSV
CSV: "date", "time", "hostname, "status (1-Up;0-Down), "pings", "up/down-time (ms)", "up/down-time (h:m:s:ms)"
CSV: "03.10.2010", " 2:37:25,92", "10.17.22.33", "1", "7", "3154", "0:0:31:54"
CSV: "03.10.2010", " 2:37:34,01", "10.17.22.33", "0", "30", "809", "0:0:8:9"
CSV: "03.10.2010", " 2:39:22,06", "10.17.22.33", "1", "24", "10805", "0:1:48:5"

>fping_monitor.cmd 10.17.22.33 03.10.2010-02:43 |findstr /v /c:CSV

Ping monitor. Version: 1.1
Monitorig host by pinging and checking range time of (un)availability.
=====================================================================

[03.10.2010  2:41] Initializing....
[03.10.2010  2:41] Initial status Up
[03.10.2010  2:41] done.
[03.10.2010  2:41] First measurement may be inaccurate...
[03.10.2010  2:42] Uptime:      0:0:13:47 (1347, ms)
[03.10.2010  2:42] Downtime:    0:0:4:82 (482, ms)
[03.10.2010  2:42] Uptime:      0:0:13:99 (1399, ms)
[03.10.2010  2:42] Downtime:    0:0:13:24 (1324, ms)
[03.10.2010  2:42] Uptime:      0:0:22:38 (2238, ms)
[03.10.2010  2:43] Downtime:    0:0:22:68 (2268, ms)
[03.10.2010  2:43] Uptime:      0:0:35:62 (3562, ms)
[03.10.2010  2:44] Downtime:    0:0:8:93 (893, ms)

URL_Monitor
Модификация FPing_Monitor, но в качестве теста используется попытка получения страницы по заданному URL.
Все остальное точно такое же, кроме того, что я сделал задержку в 10 секунд между попытками получения страницы, чтобы не попасть в разряд DoS'еров.
* Скрипт написан для внешней утилиты cURL и fping.
По умолчанию, скрипт надеется найти эти утилиты в папке Tools рядом с собой.


>url_ping.cmd http://www.ya.ru

cURL monitor. Version: 1.2
Monitoring host by reading given URL and checking range time of (un)availability.
============================================================================

[12.10.2010  2:39] Endless mode is active.
[12.10.2010  2:39] Initializing....
[12.10.2010  2:39] Initial status: Up
[12.10.2010  2:39] done.
[12.10.2010  2:39] First measurement may be inaccurate...
[12.10.2010  2:39] Error: [6] Couldn't resolve host. The given remote host was not resolved.
[12.10.2010  2:39] Uptime:      0:0:13:33 (1333, ms)
CSV: "date", "time", "hostname, "status (1-Up;0-Down), "pings", "up/down-time (ms)", "up/down-time (h:m:s:ms)"
CSV: "12.10.2010", " 2:39:50,03", "http://www.ya.ru", "0", "1", "1333", "0:0:13:33"
[12.10.2010  2:40] Downtime:    0:0:19:97 (1997, ms)
CSV: "12.10.2010", " 2:40:10,00", "http://www.ya.ru", "1", "2", "1997", "0:0:19:97"

Hosted by uCoz