Ознакомьтесь с нашей политикой обработки персональных данных
  • ↓
  • ↑
  • ⇑
 
Записи с темой: scripting (список заголовков)
07:22 

Poweshell + SNMP

В Dash'e под Chronostasis'ом.

Все гораздо проще. Не нужны никакие сторонние библиотеки - все уже украдено до нас написано, и давно.
Учитывая, что нам нужно только читать знаничения OIDов, можно воспользоваться самым базовым функционалом, придуманным еще для принтеров, и доступным аж с ванильной Win 7.

Все! Дальнейшие обвязки этого ядра скрипта - вопрос личных предпочтений.

@музыка: Iron Maiden - Can I play with madness

@темы: Scripting, PowerShell

16:33 

Powershell + Registry

В Dash'e под Chronostasis'ом.

Запись, скорее, из разряда "Getting the things done".
Про шутки с настройками сетевых адаптеров для онлайн-игрушек я знаю давно. Да все руки не доходили заскриптовать одну из настроек, которая, по понятным причинам, сносилась в дефолт после очередной переустановки системы (а в те времена это было частое явление). Что ж, не знаю, пригодится когда-нибудь кому-нибудь, но пусть будет.

Суть изложена вот тут: support.microsoft.com/en-us/kb/328890

А скрипт, который ищет нужный куст реестра, и прописывает там требуемое значение - ниже. Ориентируемся на IP адрес, отданный домашним DHCP.

@музыка: Nigel Stanford - Far Centaurus

@темы: PowerShell, Scripting

01:18 

Powershell Finder

В Dash'e под Chronostasis'ом.

Надоело мне. На-до-е-ло. Использовать сторонние средства для работы с файлами на рабочем месте нельзя, все только через Проводник. А уж как Проводник может задумываться, когда даешь ему задание найти чего-нибудь файловое, думаю, знают все. Как стало модным говорить - хватит это терпеть.
Проверяем, где у нас лежит файл профиля Powershell:
$profile
После чего открываем показанный файл (или создаем, если его не существует) и вносим в него следующий код:

Перезапускаем консоль и наслаждаемся поиском файлов через Powershell.

Ну и куда же в наше время без комментариев. А комментарии таковы. Объявленная функция будет заниматься поиском файлов в текущем каталоге рекурсивно. Маску поиска мы задаем прямо при вызове самой фукнции, например
find-item "games"
Эта команда найдет в текущем каталоге все папки и файлы, в имени которых встречается games.

В функции объявлены ключи -table, -list, -clip. С ними по порядку.

-table и -list - форматирование результата. Их можно и не указывать, в этом случае вывод будет стандартным повершелловским. Каталог - кучка файлов, следующий каталог - следующая кучка файлов. Иногда это неудобно.

-table говорит консоли, что результат нужно представить в виде таблицы:


-list заставит консоль вывести данные в виде списка:


Одновременное использование -table и -list приведет к ошибке:


-clip интереснее. По-умолчанию функция ищет файлы и папки в текущем каталоге. Но что, если у нас нужный путь скопирован в буфер обмена? -clip именно оттуда его и возьмет. После чего отдаст функции, и она будет искать файлы уже в другом каталоге. Пример:
В буфере обмена находится "C:\Program Files"


Ну а если в буфере обмена не содержится правильного пути, функция отдаст ошибку и успокоится на этом:
В буфере обмена находится "C:\Program Files111"


Посмотрим, как покажет себя этот код в боевых условиях...

@музыка: Shamis Khassenov - Orhon

@темы: PowerShell, Scripting

14:40 

Powershell and Firewall

В Dash'e под Chronostasis'ом.

По мотивам спонтанно возникшего обсуждения файрволлов и их правил.
Лезем разбираться со встроенным файром в Windows 8+. В Powershell наконец-то сделали целый набор команд, который позволяет управлять правилами местного межсетевого экрана. Как и все остальное, эти правила базируются на простых словах: New-/Get-/Set-/Remove-/Enable-/Disable-NetFirewallRule с соотвествующим набором ключей. Но как же "интересно" это все работает.
Итак, для примера создадим через Powershell сетевое правило для Блокнота (да, знаю, что бред, но убивали и за меньшее некоторые люди и на Калькуляторе файры тестировали ;) ):

new-netfirewallrule -name "Test Rule" -displayname "Test Rule" -program "c:\windows\system32\notepad.exe" -direction outbound -protocol tcp -localport 11223 -remoteport 25 -group "Test Group"

Правило будет создано, автоматом будет включено, и, согласно последнему ключу, будет помещено в группу Test Group.

Казалось бы, все хорошо. Да не тут-то было:

В частности, будет начисто заблокирована возможность менять путь к контролируемой программе и порты, по которым она сможет общаться с сетью. В то же время если создать такое же правило в GUI руками - все работает. DAFUQ?

Проверяем одну маленькую догадку. Удаляем все созданные правила и создаем его заново:

new-netfirewallrule -name "Test Rule" -displayname "Test Rule" -program "c:\windows\system32\notepad.exe" -direction outbound -protocol tcp -localport 11223 -remoteport 25

То есть не записываем новое правило в какую-либо группу. На выходе получаем полностью редактируемое любыми средствами правило.

Проверяем еще одно предположение. Удаляем теперь уже нормальное правило, создаем заново правило в группе, используя самую первую команду, чтобы получить заблокированное. А потом даем следующее:

set-netfirewallrule -name "Test Rule" -remoteport 30

После чего обновляем GUI консоль с правилами и лезем в настройки. Удаленный порт, который изначально стоял равным 25, принял значение 30. То есть получается, что Windows (в данном случае 2012) все правила, добавленные в какие-либо группы, считает созданными ей же по-умолчанию, и ничего не дает менять через графику, но спокойно позволяет менять что-либо через черный ход Powershell. Чудны дела твои, MS, хотя подобный подход уже был реализован, например, в Exchange, где через графику даже видно далеко не все.

Ради интереса попробовал поиграться с группой, в которую это правило было утрамбовано. Нифига. Единственным методом исправить группу или удалить правило из группы - удалить правило и создать его в другой группе или вообще без нее, если нужно именно это. Более того, среди всех команд Powershell нет вообще ничего, что работало бы именно с группами, а не правилами. Печально это. Выходит, что старый netsh еще не совсем вышел из моды, а вот с ним мне подружиться так и не удалось :(

@музыка: Sandra - Around my Heart (2006 edition)

@темы: PowerShell, Scripting, Этот безумный мир

01:32 

Network configuration

В Dash'e под Chronostasis'ом.

Тот самый случай, когда понимаешь, что Powershell не всесилен. Точнее не так: не во всех операциях он однозначно и безусловно удобнее, чем опостылевший GUI. Да, речь о настройках сетевых адаптеров.
Конечно, в случае энтерпрайзов начальные настройки сетевух серверы получают посредством DHCP, и это правильно. А как уже дальше будет настроен тот или иной сервер - дело десятое. Но попадаются случаи, где DHCP нет, а сервер поднять надо. Если он поднят в редации Full - проблем не возникает, пощелкал мышкой, вбил требуемое, закрыл окна. А если это Core?

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

Итак. Делается настройка сети в несколько этапов.
Этап первый. Получаем индекс того сетевого адаптера, над которым будем производить все действия. По дефолту первый (с которым чаще всего и приходится работать) адаптер обладает индексом 12. Все последующие шаги будут проводиться именно над ним.
Этап второй. Сбрасываем информацию об уже имеющемся адресе. В условиях отсутствия DHCP там будет стоять APIPA-адрес.
Этап третий. Назначаем адаптеру новый адрес и маску подсети. Внимательные люди сразу спросят - а как же шлюз по-умолчанию? Он же в той же группе контролов в GUI, что и адрес с маской. А вот шлюз будет задан позже и совершенно другой командой.
Этап четвертый. Сбрасываем информацию о шлюзе по-умолчанию, если она имеется. На свежеустановленном сервере с APIPA-адресом ее не будет, но мало ли. Интересно, что среди всех команд powershell есть команда set-netroute, но применить ее именно к шлюзу по-умолчанию, чтобы его исправить, не получится.
Этап пятый. Прописываем нужный нам адрес в качестве шлюза.
Этап шестой. Прописываем адреса DNS-серверов, если это требуется.

Вот такой список. Теперь как это выглядит в коде Powershell.



Вот такой код в своем самом базовом и простом сценарии с одним сетевым адаптером. Если их больше, то и работы скрипту добавится. Хотя логика будет та же.
Все же прощелкать окошки, действительно, проще. С другой стороны, на некоторых достаточно древних железках каждая прогрузка каждого окна займет уйму времени, а powershell-консоль запускается ровно один раз и выполняет все разом.

@музыка: Sandra - Heaven can wait (эх, далекое зеленое нубство...)

@темы: PowerShell, Scripting

19:04 

SQL via Powershell

В Dash'e под Chronostasis'ом.

Делать было решительно нечего, а идея витала в воздухе давно. Небольшой скрипт с шаблонами для работы с SQL сервером (в частности, MS SQL). Возможно, пригодится в самом ближайшем будущем. Ну а если не только мне - буду рад.

@музыка: Bryan El - Solaris

@темы: PowerShell, Scripting

01:16 

On Databases #2

В Dash'e под Chronostasis'ом.
А тем временем база принтеров успешно пересажена на "большой SQL" (пусть и в редакции SQL Express), и к ней все же написана морда на MS Access. Будет коллегам счастье и задание уже эту версию гонять в хвост и гриву.
Поймал себя на мысли, что это было даже интересно.

@музыка: Koan - After the guiding Venus

@темы: Scripting

18:00 

On Databases

В Dash'e под Chronostasis'ом.
Давненько не приходилось в VBA сидеть, ох, давненько. Сколько там уже лет прошло, после памятного димплома? Но, как бы то ни было, а небольшая база данных в MS Access наконец-то приобрела свои почти финальные очертания и отправилась на тестирование. Понятное дело, что багов там всплывет немеряно, но для того тест и нужен - вылавливать их и исправлять.
Знаю, Access по нынешним временам не тру, потому на очереди новый уровень - перевод этой базы на полный SQL. Чтоб все по-взрослому было. Ну а что, у нас есть аж целый кластер того самого сиквела, дак чего бы его кусочек не использовать под свои рабочие нужды?
И кто бы знал, Шан, как я тебе завидовал, пока ваял этот несчастный код. Потому что у меня возможности воскликнуть "Ну почему оно работает?!" не было :)

@музыка: Cisco Call Manager IVR Default MoH

@настроение: бобер, выдыхай!

@темы: Scripting

17:46 

DPM 2012 Data Source Migration

В Dash'e под Chronostasis'ом.

KnV-программирование, говорите? Их есть у нас. Точнее, не у нас, а в Редмонде. А еще точнее - в каком-нибудь из Соединенных Штатов Индии.
Есть два файловика-виртуалки. Есть у них диск D:, где все данные и лежат. Этот диск имеет свойство пухнуть, как и всякая файлопомойка. Размер VHD-файла с этим диском уперся в свой потолок в 2 Тб (старый vhd). А расширять надо. Ну что же, процедура следующая.
Внутри виртуалки-файлопомойки переводим этот диск в состояние Offline.
В консоли Hyper-V выносим нафиг файл vhd и на его месте создаем новый vhdx с требуемым объемом (vhdx поддерживает файлы больше 2 Тб).
Снова переходим в виртуалку. Находим там свежий диск, переводим его в состояние Online, инициализируем, форматируем, даем прежнюю букву, и говорим развернутой на этом сервере DFSR - а теперь, родная, реплицируй все данные с сервера-партнера. DFSR козырнула и пошла жрать файлы.

А тем временем начинает вопить DPM. Суть в следующем. Когда в DPM в группу защиты добавляем сервер и его какой-либо диск, диск этот идентифицируется не по букве, а по своему GUID (да, опять GUID, снова GUID). Когда файлопомойке дали новый диск, естественно сменился GUID этого диска. И теперь встает вопрос - что делать с группой защиты, как в нее добавить новый диск.

Можно вынести оттуда старый и добавить новый. При попытке провернуть такой фокус DPM вопит, что бекапы, связанные со старым диском, станут невалидными (то есть придется снимать заново полный бекап в те 2 терабайта, а это время).
Можно попытаться связать запись в группе защиты об этом диске с новым GUID диска. Вот это нам и нужно.

Для такого переноса существует специальный скрипт, написанный где-то в недрах MS, который называется Migrate-Datasource.ps1. Вот статья, объясняющая, что это и как оно работает.

ОК, все данные для этого скрипта есть, даем его выполнение в автоматическом режиме. Оно находит старую запись, находит новый диск, пытается их связать... и дает следущее:

Exception calling "MigrateDataSource" with "2" argument(s): "The remote
procedure call failed. (Exception from HRESULT: 0x800706BE)"

At C:\Program Files\Microsoft System Center 2012
R2\DPM\DPM\bin\Migrate-DataSource.ps1:220 char:10
+ $dpmServer.MigrateDataSource($newDataSourceId, $oldDataSourceId)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : COMException

Error in Migration

Хм, все веселее и веселее. Ладно, а что ты мне покажешь в ручном режиме? А в ручном режиме оно мне предложило выбрать запись о диске, которую надо исправить, вывело список всех дисков (их GUIDов), которые можно к нашей многострадальной записи подцепить. Этих дисков оказалась ровно 1 штука. И я не знаю, что меня дернуло просмотреть, а кому этот GUID принадлежит, но увиденное заставило отменить скрипт от греха подальше. Дело в том, что предложенный GUID принадлежал MSR-разделу файлопомойки.

Даа, делаа... Поскольку дело было уже поздним вечером, решили эту проблему отложить до утра, чтобы окинуть ее потом свежим взглядом. Вернулись к ней только спустя дня эдак 4. И что бы мы ни делали с этим скриптом, результатом всегда было только одно - предложение связать запись в группе защиты с MSR-партицией. Черт с ним, все равно приближается время полного бекапа, так что уже были готовы убить старую запись и добавить новую. Да не тут-то было:
- Народ, а вы гляньте на последнюю точку восстановления!
- Вчера сделалась? Но ведь бекап не работал?
- Андрюха, походу после этого твоего скрипта бекап все же починился.
И действительно, бекап-то шел, как и полагалось, создалась новая точка восстановления. То есть, источник данных все же мигрировал на новый диск. А теперь поднимаем глаза выше, снова читаем надпись Error in Migration.
Становится понятным, почему провалилась попытка ручной миграции. Потому что новый диск уже был связан с записью в группе защиты и не был доступным для этой операции, только и осталось, что бедную мелкую MSR предложить.

Вот такие индийские скрипты пишутся для Data Protection Manager 2012. Хорошо еще, что хотя бы они есть, тут подсказывают, что в предыдущих версиях нужно было непосредственно базу данных DPM препарировать...

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

Симантек, я, помнится, тебя материл безбожно. Как тут не вспомнить старое-доброе: "Вася! Если сможешь - прости!!!"

@музыка: Metal Gear Rising OST - Denver

@темы: Scripting, PowerShell, DPM, Этот безумный мир

13:02 

Network, profiles, ports...

В Dash'e под Chronostasis'ом.

Казалось бы, ничто не предвещало. Ну выключили все оборудование на одной из площадок (шли работы с электричеством). Ну включили его назад, проверили, что все работает, оно и работает. А SCOM ни с того, ни с сего начал вопить, что на гипервизорах Win 2012 по какой-то причине закрыты порты для файлового обмена. И это при том, что на шары тех серверов вполне себе заходишь, все, что надо, видишь. Что за напасть?
Коллега подсказал, что такое возникает в случае, если гипервизор был поднят раньше контроллера домена, и сетевой профиль сбросился с доменного на публичный. Ну а исправлять это, соответственно, перезагрузкой гипервизора при уже живом контроллере.
В этот раз по такому проверенному методу и пошли, перезагрузили гипервизоры. Но ведь неправильно это, должен быть метод сброса профиля на правильный.
Начинаем ковырять. Согласно всемирному разуму, за профили сетей у нас отвечает служба Network Location Awareness (NLA). А что, если ее перезапустить при работающем сервере в ситуации, когда контроллер домена уже жив? Настраиваем небольшую лабораторию: один контроллер на 2008 (выше все равно не поставлю ибо x86 only) и одна ВМ под управлением Windows 7 - она исполнит роль того сервера-гипервизора, что нужно вылечить. Лаборатория поднялась, все отлично. Тушим ее и поднимаем только Windows 7. Так и есть, профиль сети, которая ранее была Domain Network - example.com теперь стала неопознанной публичной сетью. Замечательно, даем рестарт службы NLA. И тут нас поджидает фейл, не смогла она остановиться.
Как же так? А вот как. В дочерних службах NLA указана еще одна - Network List Service. Она заведует списками профилей. И ее тоже надо потушить. И как раз на стадии выключения этой дочерней службы получаем ошибку "Can't stop service...". Причем ссылается ОС на внутреннюю ошибку либо в этой службе, либо в самой ОС, и, как всегда, предлагает обратиться к системному администратору (а я кто, по-твоему?!). Как же тебя корректно потушить. А что если воспользоваться старым грязным хаком, который я уже и не вспомню, откуда в моей голове - сменить тип запуска службы? Меняем на Disabled и пробуем остановить - потухла. Замечательно, теперь очередь их поднять. Сначала поднимаем дочернюю, предварительно выставив ей тип запуска Manual (именно в таком режиме она по-умолчанию). Поднялась. Теперь запускаем NLA - взлетела. Смотрим на профиль сети - Domain network - example.com. Что и требовалось.
Проверка номер два - а теряется ли в этот момент сетевое соединение с "гипервизором". По логике вещей не должно теряться, но если возникло сомнение - проверяй. Повторяем эксперимент, добавив в лабу третью ВМ - рабочую станцию администратора. Запускаем на ней пинг к гипервизору и прямо с нее проводим рестарт служб. Все отлично, "ни единого разрыва" (с). Плюс одна монета в копилку знаний.
На будущее оформляем все в виде скрипта:

@музыка: Ryan Farish - Let it rain

@темы: PowerShell, Scripting

04:25 

Printers... Many printers...

В Dash'e под Chronostasis'ом.

Когда речь заходит о принтерах,
администратор сразу же уходит в серверную,
запирается там и медитирует на мигающие светодиоды.
Потому что принтеры - это скучно.

(с) Народное творчество


Допустим, есть задача. Расставить много-много принтеров для новоприбывающих сотрудников. А потом эти принтеры сделать доступными по сети через принт-сервер. А чтобы совсем весело было, добавим в эту задачку следующие условия:
- адреса этим принтерам должны прилетать от DHCP и быть там зарезервированными
- адресация принтеров начинается с 221-го номера соответствующего диапазона, заканчивается на 250-м. Если этой части диапазона не хватает (и только в этом случае), можно идти вниз от 220-го до 200-го включительно
- FQDN принтера должно равняться букве "p" c МАС-адресом и доменом: например - p112233445566.example.com
- отображаемое имя (то самое, под которым он будет виден клиентам) собирается из шаблона Город-номер_площадки-этаж-модель-индекс (индекс - если нужен): NSK-04-304-HP555 (Новосибирск, 4-й офис, 304 кабинет, модель HP LaserJet 555
- имя порта на принт-сервере должно равняться FQDN принтера.

Хорошая задачка? Вот и мне показалось, что хорошая. А уж сколько в ней оголтелого мышкокликерства, копипаста, нервов и еще чего похуже. Одним словом - так жить нельзя.
Install-Printer.ps1

Традиционно, как готовить. Из текста скрипта ясно, что он берет входные данные из csv-файла. Формат его таков:
Name,MAC,IP
Само собой, что эти данные у нас должны быть. Пример файла ниже:

Также скрипт подразумевает, что на принт-сервере уже установлены все необходимые драйверы.

Если используются другие принципы именования портов на принт-сервере и записей на DHCP - изменить логику работы скрипта не так уж сложно. Все в соответствующих переменных.
Можно его еще и расширить, чтобы он на основании имени выбирал, на какой сервер печати принтер устанавливать. Например, если на площадке с индексом 01 свой принт-сервер, и на 04 - тоже свой. C DHCP-сервером - ровно то же самое. В общем, возможностей по его изменению - достаточно.

И, наверное, стоит завести еще одну традицию - напоминание. Предварительное тестирование скрипта в лабораторных условиях - ОБЯЗАТЕЛЬНО. В нем нет никаких действий по удалению имеющихся объектов где-бы то ни было, но тем не менее.

@музыка: Eleni Voilaris - Song to the Earth

@темы: Scripting, PowerShell

06:53 

Restart network printer

В Dash'e под Chronostasis'ом.

Из разряда "это интересно":


Вводим IP адрес, и сетевой принтер, подключенный по этому адресу уходит в полный рестарт. Чертовски полезно при смене IP адреса на принтерах, если сам принтер - у черта на рогах, а в веб-морде нет никакого средства перезапустить его.
Эта конструкция протестирована на HP LaserJet M575, работает. Надо тестировать дальше. Жаль, в радиусе досягаемости нет других моделей, которые можно безнаказанно перезагружать, ну да ничего, будет коллегам задачка.

@музыка: Eleni Violaris - Rainstriker

@темы: Scripting, PowerShell

19:27 

Boot performance degradation

В Dash'e под Chronostasis'ом.

Когда-то давно (три года назад, если быть точным) была у меня на работе проблема - рабочие станции под управлением Windows XP грузились при авторизации в домене просто безумное количество времени. В особо тяжких случаях до 20 минут доходило. На какие только ухищрения я ни шел, чтобы узнать, в чем проблема. Точнее, даже не одна проблема. Ясно, что там и сетевая производительность, и набор групповых политик (политик было много), и ПО, стартующее вместе с ОС... В общем, много чего пришлось ворочать. И "полевое" логирование приходилось включать, наверное, это уже крайняя мера.
Что характерно, семерки в той же среде не особо сильно страдали.
А вот недавно, шастал по сайтам в поисках информации на какую-то совсем отвлеченную от производительности тему (то ли Масс Эффект, то ли виртуальные машины Hyper-V), а попалась весьма любопытная статейка, в которой рассказано, как настроить слежку за процессом старта ОС прямо в Event Log. Делается просто - вот так:

В результате можем получить вот такие интересные сообщения:

Как бы это пригодилось раньше. Впрочем, и сейчас знать не помешает.
Ну а чтобы уж следовать своему новозаведенному правилу:

get-winevent -LogName Microsoft-Windows-Diagnostics-Performance/Operational | where {($_.ID -ge "100") -and ($_.ID -le "110")}

Форматировать - по вкусу :)

@музыка: Genesis - One man's fool

@настроение: Админ - всегда админ, даже с болью в горле

@темы: PowerShell, Scripting

02:45 

Hyper-V VM Time Sync

В Dash'e под Chronostasis'ом.

Пришла тут в голову мысль, а чего бы не освежить знания о том, когда нужно, а когда нежелательно включать синхронизацию времени в виртуальной машине Hyper-V с гипервизора. Выходим на соответствующую статью:
---
Time Synchronization

Updated: August 4, 2014

Applies To: Windows Server 2012, Windows Server 2012 R2

Coming soon, we are working hard in putting together this content for you.

See Also
...
---
Soon, значит? Нет, я дважды перепроверил, что это статья на сайте MS, а не Blizzard. И тем не менее - soon (tm). Кажется, по кому-то плачет судебный иск...

А началось все интересно. Есть сервер, у которого до рестарта все в порядке, а после - время убегает на час вперед. И такое уже неоднократно. Проверил часовой пояс - все в порядке, RTZ2, как и полагается. После net time /set время, конечно же, стало правильным, но только до рестарта. Сервер в домене, значит, должен тащить данные о времени прямо с контроллеров домена. А что там с источником?

w32tm /query /source

Мама дорогая, а там стоит Local CMOS Clock. Чертовщина, причем неправильная. Фиксим следующим набором команд:

w32tm /config /syncfromflags:domhier /update
net stop w32time
net start w32time
w32tm /resync

После этого в качестве источника встал КД, что и требовалось. После рестарта - настройки сохранены. Осталось лишь проверить остальные серверы, так, на всякий случай. Простенький скрипт решает эту задачку на ура:

Примечание - Get-servers - моя собственная функция, которая выбирает только те объекты, за которые наш отдел отвечает.

@музыка: Koan - When silence is moving

@настроение: клац-клац-клац

@темы: PowerShell, Scripting

13:44 

Powershell - Wait for input

В Dash'e под Chronostasis'ом.

Пользовательский ввод. Обычно его ожидание программируется без особых проблем - ставишь read-host где нужно с нужными параметрами, и дело почти всегда с концом. А сегодня задачка попалась более заковыристая. Скрипт должен ждать Х секунд, после чего запуститься заново, НО! Если в течение этих Х секунд нажата любая кнопка - скрипт должен перезапуститься сразу же. Как решать?
Быстрый гуглеж подсказывает вот такую конструкцию:

где $SleepTimeout - переменная с числом секунд до перезапуска.
Если не нажата никакая кнопка и счетчик после приращения одной единицы меньше, чем таймаут, просто ждем одну секунду. Если какое-либо из этих условий не выполняется, выходим из while, и идем к команде перезапуска. Все бы ничего, первую итерацию скрипт проходит на ура, а вот дальше начинаются проблемы. На второй и последующих итерациях скрипт считает, что "любая кнопка" уже нажата, и ничего не ждет, уходя на следующую итерацию. Сразу же. Понятное дело, что проблема кроется где-то в двух условиях.
Проверяем. counter послушно сбрасывается при каждой итерации скрипта, так что дело не в нем. Остается только $Host.UI.RawUI.KeyAvailable, статус которой не обновляется. Значит, надо как-то сбросить его принудительно. Как? Учитывая, что это буфер клавиатуры, нужно его обнулить. А обнуляется он вот так:
$Host.UI.RawUI.FlushInputBuffer()

После добавления этой строки все стало работать так, как задумывалось.

@музыка: клац-клац-клац

@темы: PowerShell, Scripting

00:19 

Temperature monitoring #2 - Powershell and UNC

В Dash'e под Chronostasis'ом.

Продолжаем разборки с SNMP и Powershell. Выяснилось, что использование сторонних библиотек очень криво работает в том случае, когда эта самая библиотека лежит на каком-нибудь сетевом ресурсе. Попытка дать в скрипте команду
[reflection.assembly]::LoadFrom( (Resolve-Path "$includeDir\SharpSnmpLib.dll") )
в случае $includeDir, равному \\server\share, приведет к фиаско.
Проковыряв советы с ServerFault и им подобных, в итоге не нашлось ничего лучшего, чем решение "в лоб" - берем эту библиотеку и тупо копируем в профиль пользователя. И подключаем ее оттуда. Просто и понятно. Параллельно еще подправили пару косяков с "лишними" слешами в путях.
Еще одна засада поджидала там, где не ждали вообще. Различие в версиях Powershell. На v2 все отрабатывает без проблем, а вот с v3 "косяки стаями пошли". Ну, не то, чтобы стаями, но в одной функции пришлось кое-что подправить. Итак, что у нас получается.
Главный скрипт:


Исправленный Invoke-SNMPGet.ps1:

По хорошему нужно было бы еще исправить и Invoke-SNMPWalk.ps1, но он не используется.

@музыка: Electronic Arts - RAP sheet

@темы: PowerShell, Scripting

01:10 

Temperature monitoring

В Dash'e под Chronostasis'ом.

В работе администратора есть такая штука, как наблюдение за параметрами среды. Иными словами - контроль температуры, влажности воздуха в помещениях. Не буду расписывать, зачем это требуется, это очевидно. Речь о другом, как это делать.
В прошлом подобная задача уже поднималась, только наблюдали не за температурой, а за состоянием серверного хозяйства. Знаю, что стандартный Ping не есть исчерпывающий и достоверный показатель работоспособности сервисов (именно сервисов, не серверов), но для серверов этого хватает, чего и добивались. Теперь задача почти такая же - есть кучка теплодатчиков, за которыми надо присматривать. Вся проблема в том, что датчики эти разбросаны георгафически, а штатные методы наблюдения за ними предполагают открытие большого количества разных программ. Поскольку всякого рода следящих утилит открыто уже и так немало, хотелось бы данный беспорядок причесать. Отдельным недостатком всех этих консолей-мониторов является то, что они молчаливы. То есть, на экране-то они покажут. что есть проблема, но за всем на экране не уследишь. А вот если будет, скажем, писк, это точно привлечет внимание. Попробуем поступить так же, как в свое время и с серверами.
Известно, что эти теплодатчики всю информацию, которую накапливают, отдают наблюдающим консолям через протокол SNMP - Simple Network Management Protocol. Несколько раз с ним сталкивался в прошлом, и всякий раз убеждался, что слово Simple там явно лишнее. Однако, в этот раз деваться некуда, с датчиками можно общаться только посредством SNMP.
Начинаем ковырять предметную область в надежде подружить SNMP и ставший уже просто незаменимым Powershell. Результат плачевен - "из коробки" Powershell работать с SNMP не умеет. Вместо этого предлагается к покупке целый набор надстроек для "мощной ракушки", который обещает нужный функционал. Ключевое слово - покупка. Понятное дело, что никто просто так "космокредитами" не поделится. И тут взгляд цепляется за следующую ссылку: vwiki.co.uk/SNMP_and_PowerShell
Ключевым моментом является библиотека со всеми необходимыми функциями. И там же представлена обвязка на Powershell для вызова этих фукнций. Утаскиваем, настраиваем, проверяем. На входе подаем IP адрес и OID сенсора. На что консоль возвращает - таймаут. Что-то не так. А что там может быть не так? Разрешенные адреса, Community name, пожалуй и все. Стоп. А ведь Community name ведь и забито нестандартное. Немного поменяв одну из функций получаем требуемый результат: скрипт подцепился к указанному сенсору, считал его показания и вывел их на экран. Почти победа, почти - потому что теперь нужно написать обвязку для проверки всех сенсоров, но это уже мелочи жизни. Итогом стал скрипт примерно следующего содержания:

Традиционно, пара слов о том, как это все готовить.
Исходные данные скрипту подаются методом, сходным с предыдущим скриптом: в каталоге с файлом самого скрипта есть папка с простыми текстовыми файлами, в которых и описаны все сенсоры для обхода. Формат данных там вот такой:
IP,OID,Community,Name,MinValue,MaxValue
где IP - адрес сенсора в сети, OID - идентификатор этого же сенсора (именно они являются чуть ли не ядром всего SNMP), Community - имя "сообщества" - читай, логина, Name - отображаемое имя (пример: "Датчик температуры в комнате 1234"), MinValue и MaxValue - соответственно, минимальное и максимальное значение для показаний с данного сенсора.
Строк заголовков в текстовиках быть не должно, скрипт сам все поймет. Самих текстовиков в каталоге config может лежать сколько угодно.
Отдельно о каталоге Include. Там хранится та обвязка на Powershell, через которую вызываются функции стащенного DLL-файла. Обвязка эта выполнена в виде трех файлов, описывающих три разные фукции. Можно их все свести в отдельный файл, но мне показалось удобнее держать их так, разбитыми. Возможно, в дальнейшем я это мнение поменяю.
Изначально фукнции Invoke-SNMPGet и Invoke-SNMPWalk содержат в себе жестко прописанный параметр Community, равный стандартному public. Поскольку это далеко не всегда выполняется, требуется изменить эти фукнции так, чтобы они принимали параметр Community в качестве аргумента. Делается это просто:

меняется на

И, соответственно:

меняется на

Вот, пожалуй, и все.

@музыка: Within Temptation - Shot in the dark

@темы: PowerShell, Scripting

11:55 

New age and Powershell

В Dash'e под Chronostasis'ом.

Вот тут пробежала ссылка на весьма и весьма приятную музыку - Eleni Violaris. Я, на самом деле, не шибко умею выражать свои чувства по поводу того, насколько сильно мне понравилось то или иное, ну не подвешен у меня язык. С другой стороны, тот факт, что эта запись вообще появилась, говорит в пользу творчества означенной барышни :)

А суть поста - архив, который отдал мне Pleer.com. Там в имени каждого трека значится ненавистное [pleer.com]. Поскольку у меня есть уже давно принятый стандарт именования треков в коллекции, надо от этого избавляться. For the Swarm!*
Имеем 11 треков. Для powershell bulk rename вообще не задача, тот способен тысячи объектов ворочать. Находясь в целевом каталоге с песенками даем стандартное:
get-childitem *.mp3 | rename-item -newname {$_.name -replace " [pleer.com]",""}

И... очень сильно удивляемся, почему это вместо требуемых имен получили кракозябы, чаще всего получаемые в случае чтения в Windows носителя, записанного в MacOS.
Поскольку имена файлов потеряны безвозвратно, заново распаковываем их из архива. Проверяем каталог, убеждаемся, что в имени каталога так же есть буквосочетание [pleer.com]. I'kill you myself!

Убираем ненужное, даем снова стандартную команду... Опять чертовщина, но уже из читаемых символов. Очень много думаем, где-то минуту, понимаем, что replace работает в режиме поиска регулярных выражений, а символы [ и ] в этом случае - маркеры. Придется экранировать. Mengsk will suffer!
get-childitem *.mp3 | rename-item -newname {$_.name -replace " \[pleer.com\]",""}

Хм... результат стал вполне ожидаемым, но это половина дела. Теперь еще желательно бы избавиться от имени исполнителя в начале каждого трека. Можно, конечно, дать вторую команду с поиском другой подстроки, однако, это не спортивно. Придется строить "конструкцию":
get-childitem *.mp3 | Rename-item -newname {($_.name -replace " \[pleer.com\]","").replace("Eleni Violaris - ","")}

Nothing can stop me!
--
* - фразы, выделенные оффтопом - для знающих и любящих SC1/2 :)

@музыка: Eleni Violaris - Song to the Earth

@темы: Scripting, PowerShell, Music

12:28 

Getting new episodes

В Dash'e под Chronostasis'ом.

Есть такой замечательный ресурс - cxz.to, в прошлом - fs.to. Файловый развал, где можно найти практически все. В том числе и сериалы, которые, традиционно, качаются с Lostfilm. Да вот засада, лостфильмовцы опять поломали свою RSS-ленту. Результат предсказуем - автоматическая закачка через торренты сгнила на корню. А новья ведь хочется.
Каждый раз заходить на сайт, смотреть, вышло что-то новое или не вышло - да что вы! Администраторы - известные ленивцы.
Чем приглянулся fs.to (я его по привычке именно так зову) - своим удобством по отношению к клиентуре. Они мало того, что предоставляют прямые ссылки на файлы, так еще и в каждом сезоне каждого сериала кладут небольшой текстовичок со списком этих файлов. Как раз то, что нам и нужно. Поехали!

С какими приправами это готовить? Да все просто. Кладем скрипт куда угодно, рядом с ним создаем файл source.txt, в котором через запятую будут указаны ссылка на список файлов, которые надо качать, и место, куда это все нужно будет качать. Слэш в конце имени целевого каталога обязателен. Вот пример того, как туда был добавлен второй сезон сериала Extant:

Ну и пара слов о том, как это все работает.
Скрипт получает из файла настроек список ссылок на интересующие сериалы, обрабатывает их по одной. В процессе обработки происходит следующее:
- проверяется наличие целевого каталога. Если он есть - все хорошо, если его нет - создается.
- скачивается информация о линках на файлы
- в цикле перебираются полученные линки: если файл уже есть в целевом каталоге - пропускаем его, если нет - добавляем ссылку на его закачку в задание BITS.
Когда цикл обработки ссылок из файла настройки завершится, будет запущено сформированное задание на загрузку файла.
После завершения задания BITS консоль подаст звуковой сигнал и покажет, что именно она загрузила.

Финальным аккордом будет являться занесение этого скрипта в планировщик. Тут уже полная свобода действий: запускать по расписанию, при логине, при старте системы - на вкус и цвет.

@музыка: Yandex Music - Amethystium

@темы: PowerShell, Scripting

17:14 

Powershell Pinger #2.1 - Разбор вывода итогов

В Dash'e под Chronostasis'ом.

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


А на практике получается следующее:


Видим, что с какого-то перепуга поменялся формат вывода той несчастной конечной хэш-таблицы. Ночью сил разбирать все это не было, уволок весь скирпт домой. Убрал все лишние обвязки, оставил в новом файле только процедуру заполнения этой таблицы. Результат - тот же, неутешительный. Начинаю вспоминать, что ж было в скрипте изменено. Каково же было мое удивление, когда после комментирования командлета Get-Date все встало на свои законные места. Хохмы ради набросал простенькую конструкцию и посмотрел на результат:


Все как и должно быть. А теперь добавляем в самое начало этого скриптика всего одну строку - Get-date, которая всего лишь выведет первой строкой текущую дату и время. Вот что получаем:


Далее на ум приходят только слова из бессмертного филатовского Федота-стрельца: "Энто ж как же, вашу мать, извиняюсь, понимать?"
Как получилось так, что безобидный вывод времени напрочь меняет форматирование во всей консоли? И самое главное - где это описано? Может быть, я, конечно, плохо искал, но вот нигде не нашел никакой документации по подобному поведению. И, самое главное, проверил это во всех доступных мне на текущий момент версиях PSH - 2, 4, 5. Везде проявляется.
Ок, а если заменить Get-Date на [System.DateTime]::Now? Результат немного предсказуем - вывод будет ошибочным :)

@музыка: David Arkenstone - 2003 - [Troika 5] Kingdom of the Sun

@темы: PowerShell, Scripting

Записная книжка

главная