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

04:10 

File operations

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

Появилась задачка, обновить базы одной из программ. Весят эти обновленные базы чего-то около 130Гб. Лежат на одной и рабочих станций сети. Обновление выполняется банальным копированием этих файлов на сервер с заменой имеющихся на сервере файлов. Казалось бы, проще не бывает - залезть по сети на рабочую станцию, скопировать папку с файлами, перейти в папку на сервере, нажать Paste и подтвердить перезапись файлов.
Все бы ничего, но свободного места на серверном диске - гигов 20. И как только нажимаем Paste - "умная" 2008-ая ОС нас посылает очень далеко: дайте мне еще 100+ Гб места, тогда я подумаю.
В общем-то, логично все, но мне-то базы обновить надо. Таскать файлы буквально по одному, да мне проще убиться, там тьма подкаталогов и в каждом тьма файлов. Винда, а винда? А Powershell'ом по зубам? Что, думаешь, духу не хватит? Ну, лови:

cd "\\network-share\"
copy-item base f:\ -recurse -force

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

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

17:09 

Powershell Pinger #2

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

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

Чем больше смотрю на указанный в коде "грязный хак" - тем больше фигею и фигею. А что делать? Иначе количество ложных срабатываний выведет из себя даже самого терпеливого коллегу. Не говоря уже о том, что я и сам долготерпением не обладаю.
Формат файлов с описанием хостов не поменялся: это все те же текстовые файлы с информацией вида ipaddress,comment, лежащие в папке config рядом с самим скриптом. Там же, рядышком со скриптом будет лежать и формируемый лог взлетов и падений.

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

@темы: PowerShell, Scripting

18:52 

Powershell Pinger

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

Логи, мониторинг... Мониторинг, логи... Этих самых мониторящих и логирующих утилит на рабочем месте уже воз и маленькая тележка. А самым информативным остается самый обычный, чтоб его, ping. Отрабатывает намного быстрее, чем монструозный SCOM и к нему примазывающиеся.
На текущий момент у нас используется выдранный откуда-то из сети коллегами уже готовый PSH-скрипт, который и занимается весьма простым делом - обходом всех узлов, заданных в банальном текстовике. Пропинговался узел - вывести его имя в консоли зелененьким. Свалился - красным. После чего спим 20 секунд, очищаем окно консоли, и снова все по кругу. Добавили еще пищалку, да и все.
Проблема в том, что держать на экране это окошко - не есть хорошо, окон на рабочем столе и так полно. Пришла в голову идея сделать так, чтобы скрипт при обнаружении свалившегося хоста выдавал в системном трее уведомление, мол, такой-то хост того, сгнил. А если на это уведомление щелкнуть - выведется полный список хостов, на текущий момент лежащих в пыли. Вот что получилось на сегодняшний день.

Как работает.
В папке, где скрипт лежит, создаем папочку config, в нее в виде txt-файлов накидываем информацию о хостах, которые будем мониторить, в следующем виде:
ipaddress,comment
Например:
192.168.1.1,router
127.0.0.1,localhost
192.168.1.3,my computer
128.0.0.1,test host
Можно все хосты в один файл утрамбовать, можно разнести по нескольким файлам, например, серверы отдельно, сетевые железки отдельно...
Внутри этих текстовиков отдельные узлы можно комментировать, поставив перед адресом знак #. К примеру, знаем, что один из серверов сейчас на обслуживании, так чтоб пингер не верещал почем зря - комментируем эту строку в файле.
Если нужно что-то добавить (либо в какой-то файл, либо просто новый файл подключить) - просто добавляем и сохраняем. Перезапускать скрипт не требуется.

Из нерешенных пока проблем.
1. Скрипт этот запускать нужно через ярлык в -sta режиме консоли. По дефолту оная консоль запускается в -mta, в этом случае обработка кликов работать не будет.
2. Инертность. В тот момент, когда скрипт нарывается на свалившийся хост, пока не завершится попытка пинга - скрипт фактически ничего делать не будет. И опять же не будет обрабатывать клики. То же самое справедливо для паузы в скрипте - особенно заметно, когда скрипт добирается до команды start-sleep -seconds $timeout и выполняет ее.

@музыка: Nicolas Jeandot - Fiery Horse

@настроение: надо думать дальше...

@темы: PowerShell, Scripting

21:43 

Resize Image

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

Для прошлого поста было отснято довольно немало фотографий, но все они вышли в диком разрешении. 3 тыщи на еще сколько-то тыщ пикселов. Да, я знаю, что Imgur может автоматом ресайзить все загружаемые изображения, но, но, но... Короче, задача ясна.
Был у меня когда-то скрипт, который позволял пачкой менять размеры у кучи картинок. Да вот беда, он в своей работе использовал модуль Powershellpack. Проблема - дистр этого модуля утерян, а страница в инете, где он лежал, убрана в архив. И модуль фактически пропал. Придется писать работу с картинками "с нуля".

PreserveAspectRatio выключен специально, иначе авторасчет величин сторон даст неверные значения.
Сохранение результатов преобразования идет в новые файлы. Перезаписать файл команда $image.SaveFile не позволяет. Ну и ладно, это не страшно.
В который раз хочется сказать спасибо МСам за то, насколько более удобной они сделали ISE в 4-й версии. Подсветка кода в строке $imageProcess.Filters.item(1).properties.item("MaximumWidth") меня просто спасла.

@музыка: Diana Lewis - Three Times Allright

@темы: PowerShell

14:12 

Автоматизация смотрелок.

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

Смотрелка - Браузер, если по-нашему, по айтишному.
А началось все... с Initial.D: читать дальше

Что-то вспомнился мне этот диалог, решил, что надо бы эту задачу расколоть.
Исследуем выдачу от Mail.ru. Все ссылки не прямые, а ведущие на отдельные страницы, уже с которых можно вытащить ссылку на сами файлы. Следовательно, вариант, который я использовал в прошлый раз, отпадает. Придется как-то ходить по ссылкам из выдачи поисковика.
Ключевой момент - как можно в Powershell пойти куда-то в вебе в режиме смотрелки? Правильно, "оседлать" смотрелку!


Вот вокруг этого скрипт и будет крутиться. Погнали!



А теперь по складам.
Первый блок ничем не примечателен, обычное объявление объектов да одной переменной. Во втором уже любопытнее, происходит, собственно "автоматизация смотрелки". Мы скармливаем подопытному браузеру исходную ссылку, заставляем его перейти по ней, вытаскиваем из исходного кода этой страницы все элементы типа "якорь", а затем при помощи хитрой магии регулярного выражения из всех этих якорей получаем ссылки, ведущие на страницы загрузки нужных файлов. Эти ссылки в виде хэш-таблицы передаются в переменную $elements.
Дальнейшее уже является повторением ранее изученного. В цикле та же автоматизация смотрелок плюс "хитрая магия" плюс загрузка файла при помощи wget.

Отдельно стоит сказать по зубодробительной конструкции
@([System.__ComObject].InvokeMember(“getElementsByTagName”,[System.Reflection.BindingFlags]::InvokeMethod, $null, $ie.document, 'A'))
которая все якоря из исходника и выбирает. Вообще есть более изящное $ie.document.GetElementsByTagName('A'), но, как выяснилось, у нее есть большие проблемы с разными версиями IE. В актуальных для Windows 7, это не работает, потому пришлось идти через запасной ход.
C хэш-таблицей тоже все весело. Изначально я вообще не планировал ее использовать, ибо зачем плодить сущности. Хотелось в переменную $elements загнать непосредственно то, что будет отдано парсером GetElementsByTagName. Не тут-то было. Парсер эти данные отдал, но как только дело доходило до третьего блока, который уже загружал отдельные страницы, переменная $elements теряла все значения. Не коллекцию элементов, а именно значения. И, естественно, третий блок валился с ошибкой и многими строками красного текста, ненавистного большинству повершелльщиков. Пришлось отделить мух от котлет, после этого все заработало.

А засада этого скрипта в том, что на его отладку было потрачено больше времени, чем на ручное скачивание всех этих 40+ файлов. Ну и ладно, зато плюс одна любопытная задачка в активе :)

P.S> Но насколько же неторопливо идет парсинг кода при помощи GetElementsByTagName...

UPD. В топку internetexplorer.application, Invoke-WebRequest же!

Важно! - из &_amp нужно убрать символ подчеркивания, парсер - нехороший человек.

@музыка: The Offspring - Secrets from the Underground

@темы: PowerShell, Scripting

17:24 

Initial D OST

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

Добил таки этот опус. Понял, что заиметь некоторые треки в музыкальной коллекции просто необходимо. Действия стандартны: гугл, запрос Initial D OST, пара-тройка страниц, на одной из них находится прекрасное - список треков со ссылками. А рядом другая - скачать все оптом. ОК, нажимаем ее, говорят - регистрируйтесь. ОК, адреса вида @mailforspam.com всегда к вашим услугам. Захожу уже под логином, дают отлуп - авотфиг, дайте нам немного денег на поддержание серверов, тогда и отдадим все оптом. Нет, так не пойдет. Присмотрелся внимательнее на ссылки к песенкам по-отдельности - бааа, да они прямые! Открываем исходный код страницы и видим просто прекрасное:

Ну и далее по тексту. Эту радость ведь вполне можно обработать при помощи Ракушки. Кнопки в зубы, сохраняем страничку с исходником в links.txt:

На выходе получаем не менее прекрасный список из готовых к употреблению гиперссылок. В буфер их и в BITS!
Связка отработала, как и ожидалось. В каталоге загрузок появилось около 40 файлов, ссылки на которые нашлись. Вот только... ни один из них не являлся файлом .mp3. Засада. Для проверки догадки ткнул на одну из тех "прямых" ссылок на веб-сайте - отдали страницу с приглашением: а теперь ткните вот в эту динамическую(!) ссылку, и будет вам счастье.
На что я плюнул, и пошел искать это самое счастье в других местах. ИЧХ, нашел.
Итого:
- задачка с парсингом ссылок порадовала;
- скрипт работы с BITS все же пригодился;
- регулярки - ЗЛО :)

@музыка: Fastway - Revolution

@темы: Scripting, PowerShell

17:40 

Буфер обмена и загрузка файлов #2

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

Теперь - банановый (с)
В смысле - теперь это чудо умеет общаться с BITS:


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


Посмотрим, что будет лучше.
UPD. Спасибо Cybeon. Нафиг временный файл:

@музыка: Wuauquikuna - Sweetheart Merceditas

@темы: Scripting, PowerShell

17:55 

Буфер обмена и загрузка файлов.

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

Надоело при помощи цопипасты загружать файлы из нескольких ссылок. Выделить ссылку, скопировать, вставить в браузер. Дождаться, пока вылезет окно сохранения файла, нажать ОК. А потом все это повторить n раз... На-до-е-ло. Хочу так: есть куча ссылок (прямых), выделить их все, скопировать в буфер, нажать 1 (одну) кнопку и получить все разом.
Заодно отметим переход на Powershell 4 (давно пора было это сделать, ISE стал заметно удобнее).

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

@темы: PowerShell, Scripting

15:42 

Powershell + Gmail + Imgur.com = ... part 3

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

А зачем нам вообще какая-то выделенная папка для хранения фотографий, которые нужно отправить в веб? У нас же есть потрясающий пункт меню "Послать на... Send to...". Так почему бы им и не воспользоваться?
Для начала настраиваем сам ярылк, который будет лежать в папке %USERPROFILE%\AppData\Roaming\Microsoft\Windows\SendTo
Создаем там новый ярлык, в свойствах которого в поле Target прописываем следующее:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -f "PATH-TO-UPLOAD-sсript"
Имя и значок этого ярлыка выбираются по собственному вкусу.
А скрипт, который будет заниматься непосредственно отправкой, будет выглядеть так:

@темы: PowerShell, Scripting

01:18 

Powershell + Gmail + Imgur.com = ... part 2

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

Небольшое дополнение к скрипту отправки картинок на Imgur, закрывающее несколько моментов.
1. Считается, что в папке $UploadFolder что-то есть. Но ведь это не всегда так, от ошибок никто не застрахован. Потому проверяем эту папку на наличие там чего-либо. Если нет ничего - просто завершаем работу:


2. После того, как скрипт работу завершит, уже загруженные файлы стоило бы удалить, чтоб не мешались. Для этого последний оператор $smtp.send() оборачиваем в следующую конструкцию:

Для чего такие сложности? Из-за того, что по завершении отправки среда Powershell не прекратит ссылаться на наши файлы, и эту связь нужно сначала разорвать. Отдельно для каждого вложения и затем для всего письма в целом. После того, как связи разорваны, можно удалить все отправленные файлы. Что и делается в блоке finally. Блок же catch нужен для того, чтобы отследить любую ошибку во время передачи файлов, перехватить ее, опять таки, разорвать связи с файлами и завершить скрипт, не удаляя сами файлы.

3. Предположим, что в папке $UploadFolder пользователь хранит не только те файлы, которые предназначены к отправке (всякое бывает, помним?). Музыка, тексты, еще что-то. Выберем из них только те, что можно отправлять. Это JPG,GIF, PNG.


Окончательный вариант скрипта после всех этих изменений - ниже.

@музыка: Stellardrone - Light Years

@темы: PowerShell

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

главная