← на главную
10 заметок с тегом

PowerShell

ArrayList и производительность массивов в Powershell

Powershell — язык весьма великодушный к программистам, почти всё в нём делается легко, интуитивно, и не требует особой подготовки и продумывания от автора кода. Однако, при выходе на объемные задачи начинают выстреливать некоторые вещи, которые для удобства изначально выполнены неэффективно.

По одной из задач мне требовалось обрабатывать большие объемы данных (сотни тысяч и миллионы строк таблиц). На тестовых множествах всё работало хорошо, но на прод данных скрипт начинал работать непозволительно долго. Я провел профилирование и выяснил, что с ростом количества данных всё больше времени (с нелинейным ростом) начинает занимать операция добавления элемента в архив.

$array = $array + $newElement — что может быть интуитивней? Оказалось, массивы в Powerhsell это имутабельные объекты, и поэтому предыдущий код фактически создает новый неизменяемый объект из всех элементов предыдущего массива и одного нового. Конечно, на больших объемах массивов такая операция будет занимать всё больше времени, и нелинейный рост вполне объясним. Этой неэффективности лишен специальный тип данных ArrayList — это тот же массив, разве что элементы добавлять самым очевидным способом через «плюс» в него нельзя.

Вот код, на котором я проверил время работы цикла из добавления N случайных строк к массивам в умолчальном варианте и варианте ArrayList

На 10 тысячах операций результаты примерно похожи — отличаются в десятки процентов. Но уже на сотне тысяч разница — на порядок. При этом время работы через ArrayList растет линейно вместе с количеством циклов, а у классических массивов — экспоненциально

Вот такие тонкости вскрываются спустя годы работы с языком. С другой стороны, это хорошо характеризует его в положительном плане — сколько за это времени гигабайт csvшек и джейсонов было перелопачено без этих ваших ArrayList?!

 1   21 ч   PowerShell

Забрать своё из облаков: kenk-vk-enricher 1.4

Допилил скрипт обогащения дампа Вконтакте. Теперь скрипт качает видео в разделах Видеозаписи, Стена и Сообщения — закачка идет через yt-dlp, перед использованием желательно обновить его до свежей версии, и залогиниться в ВК в одном из бразуеров на машине, тогда yt-dlp сможет использовать куки и больше видео будет доступно для скачивания. Также скачиваются аттачменты типа «файл» на стене и в сообщениях (те, что доступны по прямым ссылкам).

Сейчас актуальной версией скрипта мой личный профиль выкачивается на почти 200 гб, сказываются видео файлы в переписке и на стене — часто репостились интересные чужие видосы, и всё вместе занимает прилично места. Ну да больше-не меньше.

Скрипт на гитхабе: https://github.com/alexbatishchev/kenk-vk-enricher

Слава роботам!

 55   27 дн   PowerShell   Забрать своё из облаков   КЭНК

Забрать своё из облаков: kenk-vk-enricher

Причесал и опубликовал скрипт, докачивающий в дамп официальной выгрузки из ВКонтакте картинки в переписку (сообщения) и фотоальбомы. Фотки выкачиваются и складываются заодно внутрь дампа в папки с именами, соответствующими оригинальным альбомам, а если они были опубликованы с подписью (как например часто было при параллельной публикации в ИГ) — подпись сохраняется в отдельный текстовой файл рядом.

В дампе переписке все файлы даются прямыми ссылками. А вот в дампе стены картинки прописаны ссылками вида https://vk.com/photoXXXXXXXXX_XXXXXXXXX — но тут был придуман хитрый ход, немного исправляющий ситуацию. Так как среди фотоальбомов есть «Фотографии на моей стене», то если сдампить их и из кода страницы выдернуть и прямые ссылки на файлы, и ссылки photoXXXXXXXXX_XXXXXXXXX (которые там есть), то можно закешировать это соответствие и подставить потом известные картинки в код выгрузки стены. К сожалению, так можно обойти только картинки, и только картинки ваши — репосты от других пользователей или групп так и останутся со ссылками на данные в серверах ВК. Как до них добраться без URL оригинальных файлов непонятно — с парсерами картинок ВК в интернете такая же беда как и с видео. Хотя жаль, стену со своими публикациями хотелось бы содрать в максимально полном виде, включая и репосты.

За недолгое время с прошлой публикации yt-dlp успел разучиться качать видео из вк, и вновь научился этому в свежем апдейте — похоже что война апишников с реверс-инженерами идёт денно и нощно. С учетом этого, выкачку видео пока думаю не реализовывать.

Забавное наблюдение — в дампе стены есть уже удалённые вами сообщения (с пометкой «Запись удалена»). Так приятно что заботливые товарищи всё хранят даже после удаления (евпочя).

КЭНК! Слава роботам!

 52   1 мес   PowerShell   Забрать своё из облаков   КЭНК

КЭНК: безопасно храним секреты для скриптов PowerShell

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

Понятно, что харкодить креды в источниках или держать их в конфигурационных файлах скрипта — дело пропащее. Даже если зарезать на уровне файловой системы доступ только для учетной записи, от которой должен стартовать скрипт, остаётся возможность администратору сервера эти права изменить и данные прочитать. Неаккуратненько выходит ©.

К счастью, в Windows есть магическая штука на этот случай — Secure Strings — волшебство которых в данном случае заключается в том, что они работают с учетом контекста учетной записи, от которой запущены. Поэтому, если задать пароль ($pw = Read-Host -AsSecureString) прогнать его через ConvertFrom-SecureString ($pw | ConvertFrom-SecureString) и результат записать в файл, то на выходе будет чудесная буквенно-цифровая белиберда. А обратно эту белиберду можно превратить в пароль (Get-Content .\password.txt | ConvertFrom-SecureString), но только вот пароль правильным получится только если это преобразование работает от той же учетной записи, под которой шло прямое кодирование.

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

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

В интернетах пишут, что в свежих версиях павершелла появились интеграции с системами хранения паролей, но до этого мои руки пока не дошли — привычное работает, роботы трудятся, люди отдыхают

Пример кода, иллюстрирующий подход:

Ссылки по теме:

https://www.techtarget.com/searchitoperations/tutorial/How-to-secure-passwords-with-PowerShell
https://www.travisgan.com/2015/06/powershell-password-encryption.html

Слава Роботам! КЭНК!

 55   3 мес   PowerShell   КЭНК

КЭНК: тихое удаление обновления Windows по номеру KB

Задача: тихо удалить с хоста обновление Windows по номеру KB.

Какое-то время проблема легко решалась через wusa.exe /uninstall /kb:XXXXXX /quiet, но теперь в Windows 10 команда с ключом quiet просто игнорируется, а без ключа — задает много вопросов пользователю, что ожидаемо, но не подходит для решения задачи.

В интернетах быстро гуглится способ, который хорош, но не универсален. Способ рассчитывает на то что KB будет упомянута в имени пакета для DISM, а это бывает не всегда — в примере ниже у двух последних обновлений номера KB в имени пакета нет.

Ситуацию усложняет то, что в разных локалях ОС команда dism выдает информацию на разных языках, да к тому же не структурированным объектом — а строкой. К счастью, из строки все же можно выцепить имя пакета, а по нему — запросить подробную информацию (тоже строкой), где номер KB есть (судя по моим тестам) всегда:

Итоговое решение задачи такое:

  • смотрим список всех установленных обновлений и выдергиваем имена пакетов
  • по каждому пакету смотрим расширенное описание и ищем в нём искомый номер KB
  • если в описании найден нужный номер KB — пакет по его имени отправляется на деинсталляцию через DISM.exe /Online /Remove-Package /PackageName:$sFoundPackageName /quiet /norestart

Короткий сниппет, иллюстрирующий подход:

$sKBNumber = "4578968"
$aUpdts = dism /online /get-packages | ? {$_.Contains("Package_for")} | %{($_.Split(":"))[1].Trim()}
foreach ($sUpdate in $aUpdts) {
	$sInfo = (dism /online /get-packageinfo /packagename:$sUpdate) -join(", ")
	if ($sInfo.Contains($sKBNumber)) {
		write-host "Found package $sUpdate for KB number $sKBNumber"
		# uncomment below to uninstall package
		# DISM.exe /Online /Remove-Package /PackageName:$sUpdate /quiet /norestart
	}
}

КЭНК! Слава роботам!

 106   2021   PowerShell   WSUS   КЭНК

КЭНК: сортируем и фильтруем каналы IPTV

Решил подарить маме на новый год IPTV от широко известного в узких кругах провайдера. Этот сервис за небольшую плату предоставляет плейлисты с каналами, и главная суть услуги — то что списки каналов обновляются, протухшие источники заменяются новыми, клиент не бегает по интернетам в поисках собранных энтузизястами плейлистов сомнительного качества, и не остаётся вдруг без любимого НТВ под ёлочкой.

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

Телевизор Темп. Ровно такая же модель стала причиной больших перемен в семье моих родителей в начале 1980-х

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

По итогу размышлений принимаю решение реализовать компромиссный вариант. По мере протухания каналов и жалоб клиента, буду скачивать и обновлять плейлист, фильровать и обновлять в настройках плеера. Но максимально всё это автоматизирую. На выходе — плейлист с центральными каналами в HD качестве и правильном порядке (Первый, Россия и тому подобное), дополненный избранными каналами про природу, путешествия, и хорошее кино. Под рукой винда — значит фигачим на павершелле.

Первая итерация — скрипт, умеющий взять плейлист, и отфильтровать и отсортировать его по заданному правилу (простой json файл). В дальнейшем, если потребуется, можно прикрутить в него скачивание провайдерского плейлиста (тривиально) и закачивание в плеер (тут будет непросто разобраться в формате HTTP запроса). Но пока так. Быстро, зло, бесплатно, работает.

Страница на гитхабе https://github.com/alexbatishchev/kenk-iptv-playlister

КЭНК!
Слава роботам!

 35   2020   PowerShell   КЭНК

КЭНК: контролируем сроки действия сертификатов

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

Итак, проблема: в некоей системе используются сертификаты пользователей. Система (и её клиентская часть) сама по себе никаких средств контроля и мониторинга сертификатов не содержит, и задача контроля срока и необходимости заблаговременного заказа, организации установки сертификатов на устройства полностью лежит на группе поддержки. Необходимо максимально исключить человеческий фактор и заставить трудиться роботов на ниве контроля сроков.

Решение. Выгружать или как-то ещё получать доступ к сертификатам в работе система не даёт, но мы можем договориться с группой поддержки, что они будут хранить сертификаты в отдельной папке с ограниченным доступом, и работать с ней при любом обслуживании клиентов — убирать оттуда ушедшие из работы сертификаты, класть вновь выпущенные и использованные в настройке. После этого остальное дело техники — по расписанию дампим сертификаты, находим в них данные о сроке окончания, начинаем присылать предупредительные письма группе поддержки заранее. Тут кстати родилась универсальная формула, позволяющая не попасть на праздники и прочие выходные  — предупреждения высылаются за 14, 5, и 3 дня до истечения срока действия сертификата.

Главный технический ингредиент — договориться с certutil, которая в разных версиях по разному выдает дампы.
В моем конкретном случае просто парсится дата окончания через

$data = certutil -dump $file | select-string -pattern "NotAfter:"

В итоге, письма рассылаются, сроки не продалбываются, клиенты довольны, человеки не держат в голове лишней информации

Пример уведомления о скором сроке окончания действия сертификата

КЭНК!
Слава Роботам!

 48   2020   PowerShell   Windows Server   КЭНК

КЭНК: сиделка для WSUS и её приключения на планете апдейтов

Хорошо настроенный WSUS работает как часы: ходит себе в интернеты за обновлениями, раздает их клиентам, и много хлеба не просит. Есть только несколько моментов: во-первых по привычке со старых версий я обычно применяю регулярную принудительный пинок, форсирующий штатную очистку базы от устаревших и ненужных объектов (честно говоря, не знаю есть ли проблема сейчас — но готово решение есть, почему бы не запускать — хуже не будет, а времени роботов не жалко).

Во-вторых, штатные средства WSUS не дают фильтровать апдейты по целевым аппаратным платформам. В итоге KB для неиспользующихся классов железа грузят базу, а руками читать описания и отклонять всё выпущенное, например, для Itanium  — ну такое.

Последний важный момент, больше относящийся не к технологии, а к процессам и менеджменту — как построить систему одобрения обновлений так, чтобы не положить одним прекрасным ночером пару тысяч хостов кривым апдейтом (за который MS через несколько дней будет извиняться, но нас это уже не спасёт). И как при этом не оставлять системы не обновлёнными надолго, по забывчивости например. Здесь очень хочется исключить из процесса человека, оставив за кожаным мешком только задачу быстрого контроля ключевых параметров.

Трент Резнор сказал, что BSOD тут — часть инсталляции, но мы то Всё Понимаем. Фото -ltrandazzo

На уровне процессов последняя задача решается выделением тестовой группы хостов, потеря которых некритична (=которых не жалко), но которые при этом активно используются (=о сбое быстро станет известно). На эти хосты обновления одобряются сразу средствами WSUS, а по прошествии выбранного времени и при отсутствии выявленных проблем — обновления раскатываются на остальные. За это определенное заранее время хорошо бы ещё держать руку на пульсе с помощью комьюнити и тематических ресурсов — благо новости о очередном KB, превращающим комплюктеры в тыкву, разносится народным гневом как лесной пожар.

Ну а в части исключения человеческого фактора из решения — нужен робот-сиделка, что будет следить за рутиной вместо людей.

Прибежали в хату дети, притащили новый скрипт

Зовём на помощь кэнк-мена, благо у актуальных версий WSUS есть API, которое можно дёргать из PowerShell. Пара вечеров — и имеем скрипт, умеющий:

  • перемещать в целевую группу компы по шаблонам в имени (ну так, для порядка)
  • отклонять по ключевым словам апдейты, которые точно не нужны
  • искать апдейты, которые были автоматически одобрены на тестовую группу больше чем заданное время назад, и аппрувить их на все машины

Настраиваем конфиг, добавляем скрипт в планировщик, отдаем рутину машинам. Админу остаётся только посматривать на отчёты в почте, да вовремя реагировать на сигналы от группы эксплуатации и на статьи в этих ваших хабрахабрах и тридэньюсах.

Скрипт на гитахабе https://github.com/alexbatishchev/kenk-wsus-carer

КЭНК!
Слава роботам!

 39   2020   PowerShell   КЭНК

КЭНК: следитор за изменениями в контактах Exchange

На нынешнем проекте сложилась практика использования ящиков в Exchange в качестве адресной книги сразу несколькими членами рабочей группы и\или на нескольких устройствах одновременно. При этом регулярно возникала необходимость понять, когда было внесено то или иное изменение в адресную книгу ящика, а иногда — ещё и скопировать изменённые данные обратно без привлечения технических специалистов и механизмов резервного копирования. Ожидаемо, функционал требовался кастомный, а бюджет на получение дополнительного сервиса не рассчитан.

Заряжаем павершелломёт

Для целей автоматизации Exchange я часто использую Exchange Web Services (EWS) Managed API, вызывая его функции из PowerShell через библиотеку. Его применение напрашивается и тут. Можно смотреть содержимое адресной книги, дампить интересуемые данные из ящика в текстовый файл, сравнивать результаты актуального дампа и предыдущего, и формировать отчёты об изменениях. Побочный результат — раз уж мы получаем изменения, можно хранить их историю и иметь возможность ретроспективы.

Дальше — дело техники и деталей. Выгружаем поля в текстовый формат, схлопываем многоэлементные объекты в строки по формату как нам вздумается, исключаем те поля, за которыми следить не хотим. Приправляем наглядным представлением в виде HTML отчёта, выделяем цветом изменения и наносим прочую пользу клиентам сервиса. Даем возможность службе техподдержки ставить и снимать ящики с контроля добавлением в специальную доменную группу. Запускаем скрипт по планировщику с максимально возможной частотой. Роботы трудятся — а человеки пользуются результатом.

Примеры отчётов об изменении части контакта и удалении контакта из ящика

Сервис на базе этого скрипта успешно работает несколько лет. Служба техподдержки всегда может разрешить вопросы клиентов об изменениях в адресных книгах, некоторые клиенты пользуются отчётами для контроля работы в группе и оперативного отката изменений. Уникальный кастомный сервис достался заказчику в рамках общего контракта на обслуживание системы. Проблемы, для решения которых раньше требовалась работа специалиста, решаются автоматически и часто без привлечения техподдержки вообще. Чистый КЭНК!

Скрипт на гитхабе https://github.com/alexbatishchev/kenk-contacts-watcher

Слава Роботам!

 54   2020   EWS   PowerShell   КЭНК

КЭНК: автоматизация для бесплатного Veeam Backup

Прекрасный продукт для резервного копирования в виртуальных средах Veeam Backup & Replication в бесплатной версии содержит ограничения, не позволяющие комфортно использовать его на больших инфраструктурах. Ранее возможности автоматизации были сильно урезаны, в свежих версиях они расширены, но всё равно недостаточны для масштабов, актуальных на моём текущем проекте.

При этом, где-то в районе 2016 года Veeam включил поддержку PowerCLI, тогда мне попался на одном из тематических ресурсов скрипт от сотрудника Veeam Владимира Еремина, позволяющий запускать бэкапы. Ну а там где есть скрипт или API — есть и возможность дальнейшей автоматизации.

Моя идея проста: добавить в описание ВМ теги, определяющие применённый к машине план резервного копирования. Управляющие скрипты запускаются по планировщику на сервере с Veeam Backup, находят в инфраструктуре по тегам все машины, которым требуется провести копирование в этот раз, и передают эти данные на вход запускающего рк оригинального скрипта.

Со временем управляющий скрипт и оригинал обросли обвязкой (логирование, высылка уведомлений при ошибках, возможность задания путей и целевых СРК), но главная идея не изменилась:

  • программируем логику выбора виртуалок в скрипт
  • храним привязку вм к планам копирования тегами в их описаниях
  • задаем время старта планов копирования планировщиком задач на сервере

Достоинство решения — стандартные по КЭНК:

  • оно бесплатное
  • оно эффективно решает задачу максимально штатными средствами (теги хранятся в описаниях машин, расписания — в планировщике задач)
  • оно гибкое — ничего не мешает завести несколько серверов с Veeam, вешать на машины несколько тегов и добавлять машины в несколько планов
  • оно кастомизируемое — скрипт простой и его можно менять по своему усмотрению

Основной принципиальный недостаток реализованного решения — задачи резервного копирования из скрипта стартуют по очереди (при том что и сам Veeam и мощности инфраструктуры позволяют пережевать несколько одновременных потоков). Впрочем, даже с таким подходом в окно обслуживания удается уложиться без проблем, а значит усложнять решение незачем, по крайней мере пока.

велосипед на гитхабе: https://github.com/alexbatishchev/kenk-backuppo-veeam

КЭНК!
Слава роботам!

 30   2020   PowerShell   VMware   КЭНК