Записи с темой: scripting (список заголовков)
18:31 

Switch

Stance Dance

Хорошую штуку узнал сегодня про Switch(). Раньше для проверки значений я использовал этот оператор сугубо простым методом:


А оказалось, что можно, например, и вот так:

И еще много чего этот оператор позволяет, вплоть до регулярок!

@музыка: Australis - Truth of faith

@темы: PowerShell, Scripting

11:27 

Printer security

Stance Dance

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

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

В общем, спустили задачу. Из всех принтеров в настройках безопасности нужно убрать запись Everyone - Allow Print, а вместо нее подставить группу, в которую входят сотрудники, имеющие право на этом принтере печатать. Группы эти уже давно есть, хоть что-то не придется в авральном порядке создавать.

То есть имеем ситуацию: есть принтер prn-hp1235. В недрах AD есть группа с таким же именем, в ней сидит кучка пользователей, которым этот принтер через политики и подключается. Порядок действий:
- Открыть настройки безопасности принтера,
- вынести оттуда запись с группой Everyone,
- добавить группу prn-hp1235, отметив галкой разрешение Allow Print и только его,
- закрыть настройки принтера.

И так, порядка 600 штук. Весело, правда? :) Вот и я думаю, что весело. Начнем ковыряться.

В свойствах принтера есть такой параметр как PermissionSDDL. Собственно, это и есть запись того, кто и что может делать с объектом, просто записано это в формате SDDL - не самая удобная вещь для понимания. Выглядит она вот так:

Да-да, именно так. И вот эту строку (а это именно одна строка) надо как-то распарсить, изменить, измененное утрамбовать обратно в такую же строку и поменять свойства принтера.

Отправной точкой в исследованиях стала вот эта статья, за которую автору огромное спасибо. Для разбора SDDL-строки она использует объект класса Security.AccessControl.CommonSecurityDescriptor - туда заносится SDDL, там формируется нормальный список объектов и их прав, там же меняется состав этих объектов, а затем при промощи метода GetSDDLForm() формируется новая строка SDDL, которая и заносится в свойства принтера.

В теории все просто. На практике... На практике получаем, что на выходе в разрешениях принтера теряются сущности CREATOR OWNER и APPLICATION PACKAGES. И если с пакетами еще куда ни шло, то потеря CREATOR OWNER может привести к невозможности печати (в сети есть упоминания таких случаев). Что же делать? Искать, на каком этапе теряется информация об этих объектах. Выяснилось, что исчезают они как раз в момент парсинга SDDL в объект CommonSecurityDescriptor. Не умеет он, видимо, с ними работать (хотя почему?).

Пришлось искать замену. И она нашлась в лице System.Security.AccessControl.RawSecurityDescriptor. Конечно, работать с Raw немного муторнее, чем с Common (формирование записи с группой сотрудников с нуля доставило), но результат получился тот, что и заказывали.

Итак, исходная информация:
- имя принт-сервера: ps1
- маска имен принтеров: либо prn*, либо mfd* (multifunctional device)
- SID группы Everyone: S-1-1-0 (константа, не меняется нигде и никогда)

Поехали :)


Пожалуй, за всю мою практику еще не приходилось настолько плотно работать с DACL. Хорошо, что хотя бы SACL тут не участвовал :)

@музыка: Земля Ветров - Город под пеплом

@темы: Scripting, PowerShell

16:39 

Windows Print Services and Locales

Stance Dance

Что имеем? Имеем несколько уже давно развернутых принт-серверов, на них кучу установленных при помощи уже давно написанного набора скриптов принтеров. И появился у нас еще один принт-сервер, на котором тот же самый набор скриптов выдает странный результат - все принтеры по-умолчанию печатают на бумаге формата Letter, а не общепринятого А4. Какого черта?

Оказалось, что тот новый принт-сервер развернули не из образа, как обычно, а поставили с нуля из ISO-файла, и забыли при этом сменить локаль. А локаль, как оказалась, отвечает не только за шрифты, кодировки, но еще и за настройки печати, и именно это стало откровением.

Ок, поменяли локаль, перезагрузили принт-сервер. А принтерам уже пофиг, их настройки как были, так и остались, хотя новые принтеры создаются с правильным типом бумаги. Что же делать? Там больше 60 объектов, проходить по всем им и править руками - проще удавиться. Не для того к Powershell привыкал:

@музыка: Alex M.O.R.P.H., Heatbeat - Amistad

@темы: Scripting, PowerShell

22:16 

Powershell - Resize Image #2

Stance Dance

Давняя история, начало которой аж вот тут: Клац!

Посмотрев на код, решил, что жестко заданный прямо в теле скрипта путь к обрабатываемым файлам - не есть хорошо. Попутно пришла в голову мысль, а чего бы не разнообразить варианты работы? Теперь скрипт умеет делать следующее:

- обрабатывать пофайлово (параметр Identity). Скормил ему прямо имя файла, он его и обработал. Скормил через запятую пару-тройку файлов - обработает и их, например, d:\1.jpg,D:\2.jpg.
- обрабатывать пакетно целые каталоги (параметры Path и Mask). В этом случае используется имя каталога, в котором лежат нужные нам картинки, и маски расширений. Маски можно указывать через запятую, например, *.jpg,*.png
- задавать произвольные размеры картинкам (параметры Width и Height). Указываем прямо нужный размер, и он будет применен ко всем выбранным файлам.
- задавать размер с учетом соотношения длин большей и меньшей стороны (параметр Size). Указываем нужный нам размер большей стороны. Меньшая будет вычислена автоматически. Какая сторона больше - определяется также автоматически для каждого обрабатываемого изображения.

Использовать одновременно параметры Identity и Path/Mask нельзя. Хотя, возможно, я это в дальнейшем поменяю.
Параметры Path и Mask работают только в паре, по-отдельности - нельзя.

Результирующие файлы будут лежать там же, где и исходные, в имя будет добавлен суффикс _new.

@музыка: Gandalf - Titapatawa

@темы: PowerShell, Scripting

16:21 

Powershell + Yandex.Music #5 - Final

Stance Dance

Ну, поглядев на заголовок, подумал, что хочется верить, что это финал :)

Отличия от прошлой версии:
- добавил забытый(sic!) блок очистки временного каталога
- убрал работу с cookies (бесполезны)
- отказался от простой конструкции $source=@(), явно указав, что это динамический массив. Как следствие - System.StringSplitOptions больше не нужны в таком адовом количестве.
- раскидал комментарии.

Для тех, кто все же заинтересовался, как это работает, пояснение ниже.

Вся конструкция для вытаскивания музыки с сервиса Yandex.Music состоит из трех частей: этого скрипта, программки Youtube-DL, которая является "ломовой лошадью" и еще одной программки ID3.exe. С ее помощью мы развешиваем теги к стащенным песням.

В качестве исходных данных скрипт использует ссылку/-и на песни и/или альбомы на самой Яндекс.Музыке. И берет он их даже не из файла или веб-страницы, а из буфера обмена. Пример 1 - в буфере у нас лежит вот такая строка:

Это выкачает одну песенку.

Пример 2 - в буфере лежит подобная ссылка:

Будет стащен весь альбом.

Пример 3 - в буфер загнали больше, чем одну строку:

Будет стащена сначала песня по первой ссылке, затем альбом по второй.

Как "готовить"?

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

Текст финальной версии - ниже.

@музыка: Sergey Eybog - Afterword

@темы: Scripting, PowerShell

10:29 

Powershell + Yandex.Music #4 - Full Batch

Stance Dance

Подумалось тут - а чего бы не обучить свой скриптик таскать и альбомы, и треки разом? Собрал в буфере обмена целый список того, что нужно, надавил кнопочку "Download", а умная машинка сама поймет, что от нее хотят.

Теперь скрипт работает так. Скармливаем ему через буфер обмена данные. Первое, что будет сделано - попытка разбить эти данные на строки. Одна строка там будет на выходе или несколько - неважно, они будут потом поочередно обработаны и распознаны - ведет ссылка в этой строке на трек, или же она ведет на альбом. Если на трек, в список загрузки будет добавлена сама эта ссылка, если же на альбом - как и в предыдущей версии - скрипт стащит ссылки на треки этого альбома и уже их добавит в список загрузки.

Ну а в финале - пробежка по списку загрузки и, собственно, скачка нужного.

На удивление часто пришлось играться с System.StringSplitOptions::RemoveEmptyLines, как-то нервно Powershell со строками работает.

@музыка: Sergey Eybog - Get to know me better (Как перестать гореть???)

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

@темы: Scripting, PowerShell

01:35 

Powershell + Yandex.Music #3 - Album Download

Stance Dance

OST "Бесконечного лета" стал последней каплей. Я давно уже собирался обучить мой скрипт загрузки треков с Яндекс.Музыки работе с целыми альбомами, но все духу не хватало. Хотя дел там не так уж и много. Но пройти мимо этой жемчужины я физически не смог, БЛ просто обязан поселиться на моем телефоне целиком.

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

Похоже, что музыкой БЛ я буду болеть еще очень и очень долго. Похоже, она стала именно тем, что я давно для себя искал...

@музыка: Sergey Eybog - Went Fishing, Caught A Girl (я ржу с названия этой композиции)

@настроение: после открытия хорошего рута Лены - уже лучше

@темы: Scripting, PowerShell

09:34 

XPath - боль

Stance Dance

Впервые довелось воспользоваться XPath-фильтром при работе с логами Windows. Это кусок боли, причем с двух сторон. Сначала взвыл, поглядев на структуру сообщений об удалении файлов с ресурсов севрера. Обычно же как:

C этим все просто и понятно. А вот фигвам! Имеем вот такой шаблон:

Энто ж как же, вашу мать, извиняюсь, понимать? (с) бессмертный Филатов.

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

Это выберет сообщения, в которых есть указанная нода с указанным аттрибутом и нужным значением этой ноды.

Выбирать можно и по аттрибутам:

Проверяется только значение attribute1, без значения самой ноды, если такого, например, нет вовсе.

Само собой, логические операторы тоже поддерживаются:


Вроде бы и ничего особо сложного, но только когда хоть малость привыкнешь. А до тех пор - bite the bullet, как говорится. А я еще, помнится, на вычисляемые поля в select-object ругался. Тоже долго с тамошнему синтаксису привыкал, со всеми скобочками, точками с запятой, кавычками. Удобная штука, эти вычисляемые поля, не спорю, но прописывать их запаришься.

В общем, основное правило при работе с XPath - вложенные ноды - через слэш, аттрибут рассматриваемой ноды - в квадратные скобки через comm-at - @.

@музыка: David Arkenstone - Ah*Nee*Mah Project - The White Feather

@настроение: привидение выспалось, привидение довольно...

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

16:02 

DPM - Available Tapes #3 - Case Closed

Stance Dance

В топку. В топку тот скрипт, который мне дался таким потом и кровью. А все почему - потому что с точки зрения управления лентами чере Powershell DPM еще та дрянь. Простой пример: лента с одной (всего одной) точкой восстановления, для которой назначено больше чем одна Recovery Goal (ну то есть для данной точки восстановления есть бекап бекапа - вторая копия этой информации). Powershell для этой ленты говорит: Recovery Point status - Expired. Открываем содержимое той же самой ленты в GUI-консоли - бааа, да эта лента сдохнет только через пару недель. И самое паскудное - верная информация все же в консоли.

Короче, как я уже и сказал - в топку. Придется использовать встроенный в сам DPM отчет о ротации лент. Не так удобно, как мой скрипт, но данным можно будет верить, это важнее.

@музыка: Iron maiden - Heaven can wait

@настроение: не самое безоблачное, столько сил впустую

@темы: Scripting, PowerShell, DPM

09:02 

Powershell Functions

Stance Dance

На самом деле такие моменты надо собирать, запоминать и ценить. Они как раз и показывают, что не напрасно занимаешься тем, чем занимаешься.

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

Каждый раз заходить для этого на сервер - лениво. Даже воспользоваться mmc-оснастокй Services - тоже лениво. А самая главная засада в том, что даже если работать через любимый Powershell - имеющаяся там встроенная команда Start-Service не принимает в качестве параметра имя удаленного сервера, она работает только с локальной системой. Потому была написана простенькая функция, которая вызывается вообще без параметров и запускает на жестко забитом сервере жестко заданную по имени службу, используя механизм Invoke-Command. Примерно так:

И она работала себе, жрать не просила.

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

Получилось нечто вот такое. Решил, что пора бы осваивать Advanced Functions и встроенный в них man. Заодно обучил функцию работать не только с именами служб, но и с их отображаемыми подписями, так что службу идентифицировать можно разными способами.

И показал ее своему коллеге. Посмотрел он на нее, после чего в чат выдал вот такое:
- Эээ... Get-service -ComputerName %SERVERNAME% -Name %SERVICENAME% | Start-Service

После чего настал мой черед выдать:
- @#$...

И дружно ржем. Потому что весь мой велосипед реально умещается в одну строку кода, если отказаться от проверки DisplayName.

И самая мякотка - того коллегу на Powershell именно я и подсадил где-то год назад :)

@музыка: Nicholas Gunn - Flight over North Rim

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

@темы: PowerShell, Scripting

10:02 

Check DNS addresses

Stance Dance

Частенько бывает необходимо проверить сразу десяток-другой имен узлов в DNS: есть они там, нет их там, если есть - под какими адресами значатся. Каждый раз вбивать nslookup %hostname% руками - утомляет безумно. Потому набросал простенькую конструкцию:

Если узел в DNS есть - будет выведено его имя и его адрес. Если узла нет, или в процессе просмотра вылезла какая-нибудь ошибка - будет выведено только имя.

@музыка: Silence

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

@темы: Scripting, PowerShell

22:44 

DPM - Active Tasks List

Stance Dance

MS DPM - штука такая, за ней глаз да глаз нужен. Точнее, не за ней самой, а за одним типом задач - System State Protection. Частенько бывает так, что такая задача зависнет на пять-шесть часов, и только почем зря занимает ресурсы сервера. Обычно в таком случае мы просто прерываем ее и запускаем заново. Полчаса - и бекап состояния системы готов. Но для того, чтобы задачу перезапустить, ее надо увидеть. А для этого нужно зайти на сам сервер DPM. А... Согласен, слишком много "А", но тем не менее: а консоль DPM - штука очень неторопливая, да и самих серверов далеко не одна штука. Заходить на каждый и смотреть, что там творится - да проще убиться веником. Powershell to the rescue!

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

@музыка: E-Mantra - I shall not care

@настроение: Neutral

@темы: Scripting, PowerShell, DPM

18:11 

DFSR Backlog - Все сразу

Stance Dance

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

А уж что делать с табличкой, утрамбованной в переменную $output - на усмотрение конечного пользователя.

@музыка: Project Blue Sun - Besame (Radio Edit)

@настроение: а за окном дожди и хмарь...

@темы: Scripting, PowerShell

00:08 

Printer Ports and SNMP

Stance Dance

Поступила задача - на большой-пребольшой куче принтерных портов включить галку SNMP Enabled, исключая те, к которым подключены принтеры модели HP 577. При создании всех тех принтеров мы как-то пропустили тот факт, что она не ставится автоматом. Для новых объектов поправили, а что делать с уже имеющимися? Первая мысль: ну не вопрос, в одну руку порт, в другую Set-PrinterPort... Hey, cousin, it doesn't happen! (c) Командлета Set-PrinterPort не существует в природе. Ладно, но есть жабросли WMI:

Хотя и знаю, что правильнее было бы использовать Get-WmiObject -Class win32_TCPIPPrinterPort -filter 'бла-бла-бла', а не Get-WMIObject | where {бла-бла-бла}, но есть затык. В фильтр я так и не смог загнать переменную. А жаль.

@музыка: Sabaton - Blood of Bannockburn

@темы: Scripting, PowerShell

19:15 

Data Protection Manager - Backup Statistics

Stance Dance

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

Task Scheduler, все дела. Затем создается связь в Excel на полученный txt-файл, и дело сделано. При желании можно расширить и на несколько площадок, чтобы вообще всю статистику получить.

@музыка: Philippe Alexandre Belisle - Impovisation

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

@темы: PowerShell, DPM, Scripting

00:00 

Lostfilm RSS

Stance Dance

Враги-лостфильмовцы с переходом на новую версию сайта допустили то, чего я опасался больше всего - RSS уложили отдохнуть. Не работает загрузка через нее больше. Спасибо добрым людям - дали ссылку на топик старого сайта, где рассказали, что делов-то всего - получить старую RSS, заменить одно на другое, после чего скормить полученное торренту. Закавыка всего одна - торрент в принципе не работает с локальными файлами, из чего следует, что исправленную ленту нужно заливать на какой-нибудь сайт. Ну и предлагалось использовать PHP для модификации. Вот только PHP я не люблю, да и держать его не на чем.

Хм... но никто же не мешает поднять IIS. Хотя любви к PHP это не прибавит, но можно и без него обойтись. Главное, что будет куда выкладывать новую ленту.

Итак, имеем следующее.
Исходная лента доступна по адресу

В полученном xml-документе мы должны найти все вхождения

и заменить их на


Как поднять IIS и проверить, что она работает - мануалов тонны. Дальше в дело вступает Powershell:


Файл-результат будет сохранен сразу в веб-каталог IIS. Соответственно, нужны права на запись в него тому пользователю, от чьего имени будет выполняться это задание.

Дальнейшее - тривиально. Task Scheduler, запуск этого скрипта с заданным интервалом под нужной учеткой. Как только увидели, что нужный файл сформировался в каталоге IIS - натравливаем на него torrent-клиент ровно с теми же параметрами, что ранее были заданы для обычной ленты RSS LostFilm.

Готово! Можно кушать :)

@темы: PowerShell, Scripting

17:59 

Powershell Libraries...

Stance Dance

Вот раньше как было?


И это спокойно себе работало.

С недавнего времени отказало. Точнее - работает, но только если этот код вызывается из ISE. Там куча всяких библиотек подгружается в фоне. Проверяем:


Поменяли подгрузку в 5.1 Теперь приходится ручками писать:


Предупреждать надо!

@музыка: John Marting - Anywhere gor you

@темы: Scripting, PowerShell

14:53 

Powershell + Yandex.Music + MP3 Tags #2

Stance Dance

Гость натолкнул на интересную мысль. --add-metadata - штука хорошая, но требует наличия на компьютере какого-нибудь, ну хоть плохонького, но энкодера. А поставить его бывает возможность не всегда. Но мысль заключается в следующем - сохранять метаданные можно не только напрямую в результирующий mp3, но и просто в файл. Так почему бы и нет? Уж распарсить получаемый на выходе json powershell сможет всегда. А рядом с тем же youtube-dl положить маленький любимый id3.exe - и вовсе не проблема.
Остальные условия те же - ссылку для скачивания скрипт берет прямо из буфера обмена.
Поехали!

@музыка: Years & Years - King

@темы: Scripting, PowerShell

19:17 

Poweshell - Fixing Printer Group Policy

Stance Dance

Очередной день, очередные тесты. Вводим в тестовую среду виртуалку с Win 7 в качестве клиентской ОС и начинаем править скрипт таким образом, чтобы результирующие файлы были в нужной кодировке и читались как серверами, так и клиентами.
Смотрим на исходные файлы "живых" политик:
Printers.xml - UTF8
GPT.ini - Windows-1251.

Лезем скрипт, находим там строку

После чего меняем ее на вот такую конструкцию:

Через Stream Writer мы запишем Printers.xml в нужной кодировке - UTF8. Она НЕ равна Unicode, в котором Powershell соберется записать файл по-умолчанию.
С GPT.ini все проще. В инструкции

просто добавляем требуемую кодировку:

После чего gpupdate на клиентах, и наблюдаем красивые безошибочные журналы System и Application.
Дело за проверкой в боевых условиях. Нужна тестовая политика уже там.

@музыка: Ryan Farish - Sunshine in the Rain

@темы: PowerShell, Scripting

20:32 

Powershell - Printer Policy Complete

Stance Dance

Сделано. Решение "влоб" отменяется. MS XML оказался намного проще, чем я полагал все это время.
На вход - csv c полем Name (в нашем случае - ищется файл printers.csv в папке Документов текущего пользователя), где будут перечислены отображаемые имена принтеров. На выходе - заполненные политики по разливке этих принтеров пользователям на основе групп доступа. Принтеры будут расставляться членам групп с именами, равными названиям принтеров.
Политик две. Предполагается, что принтеры на первой площадке попадают в политику Map-Printers-01 и крутятся на принт-сервере ps1, принтеры второй площадки разливаются через политику Map-Printers-02 и сидят на сервере с названием ps2.
Если вдруг скрипт обнаружит, что для какого-то принтера не создана группа доступа, скажет об этом и пропустит принтер.
Если будет обнаружено, что в целевой политике уже есть запись для добавляемого принтера - будет предложено ее (или их, если их много - бывает и так) пересоздать. Если отказаться от этого - принтер будет пропущен.
И важный момент. Обе политики уже должны существовать, и в них должен быть заведен хотя бы один принтер. В противном случае в каталоге политики в SYSVOL будет отсутствовать файл Printers.xml, а создавать его политика не обучена (мне было лень).
Поехали!

@музыка: Joe Satriani - Speed of Light

@настроение: Getting the things done!

@темы: PowerShell, Scripting

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

главная