Записи с темой: powershell (список заголовков)
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

@темы: Scripting, PowerShell

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 (Как перестать гореть???)

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

@темы: PowerShell, Scripting

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

22:50 

PS Function Parameters

Stance Dance

Так, чтобы не забывать. Эдакая рыба при объявлении параметров в функциях PS:

Параметр -> Атрибуты параметра -> валидация параметра -> тип+имя параметра.
Пример:

Нет, все же формат объявления параметров - одна из тех немногих вещей, которые мне в PS категорически не по нраву. Но что поделать, we take all they can give, right? (c) Dante

@музыка: W.A.S.P. - Sex Drive (да, да, самая музыка на ночь, а завтра с утра на работу)

@настроение: но все же можно было как-то проще сделать эти несчастные параметры...

@темы: PowerShell

18:33 

Powershell - Runtime

Stance Dance

Запись, скорее, из разряда "не забыть проверить":

Одна и та же операция в двух разных подходах. Первый вариант ощутимо быстрее. Вероятно, это может помочь с оптимизацией давешнего скрипта по подсчету доступных лент DPM. На текущий момент он может выполняться аж 20-40 минут, в зависимости от задумчивости каждого конкрентного сервера. Это много, слишком много.
Все же хорошо иногда свои же собственные записи перечитывать. Иногда сознание что-то цепляет оттуда и прямо таки кричит: "Видишь??? А теперь сравни вот с этим."

@музыка: Iron Savior - Crazy

@темы: PowerShell

17:25 

Guest VM provisioning

Stance Dance

Очень хорошая статья на тему автоматической начальной настройки гостевой ОС:
Specialize Windows Server Hyper-V guest OS automatically - Клац!
Интересна она тем, что применить изложенный метод можно не только к Hyper-V, но и к любому гипервизору, способному работать с файловой системой оффлайн-ВМ. Потому как на одном из этапов нужно будет подложить в гостевую ВМ файл с параметрами машины.

Попробовав выполнить все описанное в VMWorkstation, могу сказать - работает. Если требуется поднять сразу пачку ВМ - все будет значительно быстрее, чем вбивать параметры сети и имени машины в домене руками. Хотя в моем случае нашлась пара подводных камней.

Первое. Засада с файлом ответов unattend.xml. В статье говорится, что ветку Autologon необходимо прописывать в этап конфигурации oobeSystem. В моем случае это не так, пришлось записать его в этап Specialize, иначе не работает.

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

@музыка: Nigel Stansord - Deep Space

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

@темы: Virtualization, VMWare, PowerShell, Hyper-V

10:02 

Check DNS addresses

Stance Dance

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

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

@музыка: Silence

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

@темы: Scripting, PowerShell

02:32 

DPM - Available Tapes #2 - In depth

Stance Dance

Попробую собрать в кучу все свои мысли по поводу давешнего скрипта подсчета доступных лент на серверах Data Protection Manager.
Итак, что у нас имеется. Имеется жутко тормозная консоль, которая представляет в сводной таблице сведения о доступных лентах в неудобном формате: Free Tapes и Expired Tapes. Штука в том, что Free Tapes отражает общее количество доступных лент, включая просроченные (expired). И в то же время если докапываться до подробностей - сам же DPM различает эти сущности - Free и Expired. Для именно свободных лент целый пул есть, который так и называется - Free. В скрипте он фигурирует, там, где подсчитываются пустые ленты. Вот этот формат вывода информации тоже хотелось бы поменять на более вменяемый - X доступных лент, из которых Y пустых и Z просроченных.

Собственно, с подсчетом пустых лент сложностей никаких. Взять все ленты, которые есть в данный момент в библиотеке, да выбрать из них те, что принадлежат к пулу Free. Невеликого ума задача. С просроченными дело обстоит куда сложнее (ну и интереснее, теперь я уже могу это сказать).

Что такое просроченная лента? Это кассета, на которой истекло время хранения всех бекапов. Отдельного признака Tape Expired (или чего-то подобного) у объекта Tape не нашлось, стало быть, придется опрашивать непосредственно ленты. Ну, не сами ленты, конечно же, а сведения о них в базе данных DPM. ОК, выбираем все ленты, не принадлежащие к пулу Free, и относящиеся к типу "Архивная лента" (иначе в выборку попадут чистящие кассеты, а это нам не нужно). А потом в цикле просматриваем их содержимое:

Get-RecoveryPoint -Tape $Tape

С этого момента начался мой персональный ад. Когда-то давно использовался найденный на просторах интернета скриптик, который и занимался подсчетом лент, как свободных, так и просроченных. Да вот беда, неделю назад нашлось расхождение между тем, что показывает этот скрипт, и тем, что показывает сам DPM. А именно - консоль показывает ленту как просроченную, а скрипт утверждает, что на ней еще есть "живые" бекапы, и затирать ленту нельзя. Более того, лента "сдохнет" только через месяц, который, к слову, уже почти истек. Вот эту чертовщину и нужно решить.

Хорошо, давай смотреть, что у нас на такой проблемной ленте лежит. Там лежат такие же бекапы, что и везде, они прекрасно видны через Get-RecoveryPoint. We need to go deeper... Берем один из таких бекапов (они называются точками восстановления в терминах DPM) и изучаем его под микроскопом:

Get-RecoveryPointLocation -RecoveryPoint $RP

Команда выдает нам тучу объектов, которые technet называет RecoveryPointLocation, в скрипте они обозваны как RSL- RecoverySourceLocation (и не спрашивайте, почему так, я сам не до конца разобрался, что меня заставило именно так их назвать). Как я понял - это карта размещения данных в точке восстановления на кассете. И уже с вот этими объектами связаны временные метки, когда точка восстановления была сделана, когда она сдохнет, там даже отдельное поле есть - Validity. Собственно, прошлый скрипт именно на это поле и смотрел, но делал это как-то странно: он смотрел только на первую такую запись. Если она просрочена - помечал всю точку восстановления как сдохшую. И шел себе дальше.

Казалось бы, все просто - исправив пару строк пройтись в цикле по всем этим записям, и если не найдется ни одного вхождения Validity = Valid, точка восстановления должна быть признана сдохшей. Как только попадется хоть одна запись вида Validity = Valid, точку восстановления помечаем как живую и прекращаем ее обработку, перейдя к следующей. Вот тут-то расхождение в показаниях и раскрылось: на ленте куча RSL, для которых поле Validity = Valid. Но консоль же эту ленту так же упорно видит как просроченную. И вот-вот ее затрет, лишив возможности разобраться окончательно.

В попытках рассмотреть под микроскопом уже сами RSL я себе чуть не сжег остатки мозга и глаз. Везде сплошные IDшники и ничего более, буквы и цифры чуть ли не снились. Подключил коллегу, который те бекапы и настраивал. Смотрим вместе с ним, видим поле Generation. Далее диалог двух уже основательно окосевших от обилия буквенно-цифровой информации людей:

- Стоп. Поколения, это что еще за хрень?
- Ыы, там отцы и сыновья. А может ли это быть бекапом бекапа?
- Хм. Может. У нас же настроено копирование с ленты на ленту. Давай сравним поколения и временные метки.


Эх, счастье было так возможно, так близко. Но нет, для разных RSL на той ленте были "живыми" и сыновья, и отцы. Нашлись все варианты комбинаций Father/Son, Valid/Expired. То есть так просто по полю Generation тоже не отфильтруешь. Но ведь консоль это как-то делает! Да и мысль о "бекапах бекапов" покоя все не дает.

$RSL | Get-member

Покажи мне, что еще есть у этих записей. Та же куча IDшников, но в свете обсуждения копий лент глаз резанул параметр MediaMapList. Это уже интереснее. Берем одну RSL и заглядываем в нее. А там... А там ни что иное, как список ID лент, на которых лежат копии этой самой точки восстановления. Вот оно! Картина вырисовывается такая:
- берется лента, на ней читаются точки восстановления.
- берется точка восстановления, читаются все объекты RSL.
- если во всех объектах RSL в поле Validity стоит Expired - проблемы нет, лента просрочена.
- если в какой-то RSL в поле Validity видим Valid, нужно определить, что именно еще не умерло: запись на этой самой ленте, или информация на совершенно другой ленте (тот самый бекап бекапа).
- смотрим на параметр MediaMapList и получаем оттуда ID всех лент, задействованных для этой RSL.
- если среди всего там имеется ID текущей ленты, "живая" информация лежит на именно этой ленте, и значит, всю ленту помечать как просроченную нельзя. Если же среди найденного нет ID текущей ленты, "живая" информация находится на других лентах, а значит, точку восстановления на текущей ленте можно пометить как просроченную.
Вот именно последних двух шагов ранняя версия скрипта и не делала. И именно этим обусловлены расхождения в результатах. Щелкание кнопок, дописывание соответствующего кода, тестовый прогон на нескольких "подозрительных" лентах - результаты что в скрипте, что в консоли - идентичны. Прогон на нескольких серверах - все прекрасно.

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

@музыка: Земля Ветров - Моя земля (для разнообразия)

@темы: PowerShell, DPM

16:42 

DPM - Available Tapes

Stance Dance

Когда-нибудь я распишу этот скрипт, и то, что он делает, очень подробно. Но не сейчас. Сейчас лишь ограничусь тем, что он собирает данные по доступным лентам в ленточных накопителях. Доступные - значит свободные для записи. В эту категорию попадают как пустые ленты, так и те, на которых истекло время хранения всех точек восстановления. Этот скрипт, вроде бы и небольшой, сожрал мне мозг начисто. Но он работает. Медленно, но работает, причем не вступает в противоречие с консолью DPM, а именно это меня и бесило больше всего.

Но как бы то ни было - задача выполнена.

@музыка: Nigel Stansord - Deep Space

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

@темы: DPM, 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

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

главная