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

Conversion

Stance Dance

Когда-то давно попалась мне папочка под названием Two Steps from Hell. А в ней куча треков от одноименной группы, все в формате WAV. Чтоб без потери качества, так сказать. Одно плохо, в телефон не закинешь, да и места много едят. Надо бы их всех отконвертировать в идеологически верный mp3, который понимает практически все звукоиздающее барахло. Хотя нет, идеологически верным будет ogg, но мой телефон все равно его не поймет.
Вроде бы на компе есть AIMP с его конвертером. И в большинстве случаев этого хватает. Но в случае пакетной обработки он может и спасовать. Что ж делать, не руками же все это перелопачивать (папок там немало).
Кинул клич по своему контакт-листу, общими усилиями достали завалявшийся lame.exe. Дело за малым, все тот же Powershell в руки:


Крутится, жрет папку, на которую я его натравил...
Забавляет вывод от lame.exe в окне ISE - он весь краснющий, как помидор. Красный в PSH - цвет ошибок, сначала зело напугал :)
Ах, да. Если нужно удалить исходный файл сразу после преобразования - раскомментировать строку #Remove-Item $file.fullname. Без предварительного теста (например, с ключом -whatif) - не рекомендуется, впрочем, так всегда.
P.S. А потом смотрим на строку с определением целевого имени файла и понимаем, что можно было сделать еще красивее:

$destination=$file.fullname -replace $file.extension, ".mp3"

Впрочем, вариант с построением целевого имени из отдельных кирпичиков кажется более наглядным.

@музыка: Roxette - Fingertips

@темы: Scripting, PowerShell

19:27 

DPM 2012 Enumerate tapes scritpt

Stance Dance

Забавный случай. Имеем скрипт, который обсчитывает все ленты в библиотеке, подконтрольной DPM 2012. Фрагмент скрипта выглядит вот так:

$RPs=Get-RecoveryPoint -Tape $Tape
$ExpDate = $RPs[0].recoverysourcelocations[0].expirydate

И вот этот кусок ведет себя на разных системах по-разному. На одной из рабочих станций - все ок. На сервере - все ок. На другой рабочей станции - все плохо, дает ошибку вида Unable to index into an object of type...
Сначала думали, что что-то не так с самим шеллом от DPM на проблемной машине. Переставили, результат нулевой.
Проверили догадку относительно прав на сам DPM и работу с ним. Отмели, потому что на сервере под той же учеткой, что и на проблемной рабочей станции, все ок.
Начал ковырять. Скрипт валится всегда на одних и тех же кассетах. А записей на этих кассетах - по одной штуке на каждую. Получается, что на выходе мы получаем обычную скалярную переменную, которую скрипт затем пытается представить как массив, и выдрать из него самый первый элемент с нулевым индексом. И получает отлуп. Проверяем:

PS C:\temp> $a=12
PS C:\temp> $a[0]
Не удается индексировать в объект типа System.Int32.
строка:1 знак:4
+ $a[ <<<< 0]
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : CannotIndex

Уже интереснее. Ковыряние сети привело к корню проблем: на такой фокус с обращением к обычной переменной, как к массиву, способен Powershell 3.0 и выше. А на проблемной станции - увы и ах, всего лишь вторая.
Что ж, учтем на будущее.

@музыка: Koan - Dance of Nereids

@темы: PowerShell, Scripting

03:25 

Event Log + Powershell

Stance Dance

MS в своем стиле. Давно такой зубодробиловки не встречал. Впрочем, из стана *nix, наверняка, наоборот, могут послышаться возгласы одобрения, ибо "все есть файл".
Задача. Необходимо сделать так, чтобы по возникновению в журнале Windows события с определенным кодом администратору (или другому причастному к процессу) на почту падало письмо с содержанием этого сообщения. Заскриптовать сам процесс отправки письма - не проблема. Проблема в это письмо утрамбовать содержимое самого сообщения.
Что попытались сделать? Нам известен код события. Что ж, по возникновению этого события ищем все события с этим кодом, сортируем их в порядке убывания, отсекаем самое первое в выборке. Это и будет искомое. Дальше по скрипту вытаскиваем его содержимое, трамбуем в письмо, отсылаем депешу. Казалось бы, проблема решена.
А вот и нет. Проблемы начинаются, когда копируется сразу несколько мелких файлов. В этом случае вся наша выборка становится сбойной, и в итоге события теряются, письма приходят только на часть их. Что же делать?
Вечерний треп с Cybeon принес весьма любопытные результаты. У каждого события в логе есть уникальный номер. Вот вытащить бы его, отдать скрипту, а скрипт уже пусть ищет именно это конкретное событие и пакует его в письмо. Идея хорошая, но как? А вот так:
blogs.technet.com/b/otto/archive/2011/08/24/tri...
Как уже выше было сказано - все есть файл. Именно файл нам на помощь и приходит.
Вкратце - создаем болванку задания, экспортируем его в XML файл и убиваем болванку. Она нам больше не нужна. А потом правим полученный XML файл и вносим туда следующее:

После чего импортируем этот файл в оснастку назначенных заданий. После таких вот премудростей наше задание будет отдавать три параметра: имя журнала, в котором возникло наше событие (eventChannel), его критичность (eventSeverity) и, та-дааааам, уникальный код этого события (eventRecordID).
Итак, сами значения мы выцарапали. Как их передать в скрипт? Через параметры командной строки:
powershell -command %PATH-TO-sсript% -eventChannel $(eventChannel) -eventRecordID $(eventRecordID) -eventSeverity $(eventSeverity)

А последний шаг - уже в том скрипте, который будет выполнять все действия по отсылке писем, первой строкой объявляем полученные параметры:
param($eventChannel,$eventRecordID,$eventSeverity)

На этом все. Но осталась важная ремарка - не дай вышние ошибиться хоть где-нибудь в регистре в именах всех этих переменных. Как оказалось - регистрозависимо тут все.

Почему передачу данных в скрипты из журналов до сих пор не сделали более менее дружелюбной к администраторам - об этом остается только гадать. Несмотря на все улучшения в Windows 2012 - пилить ее еще и пилить.

@музыка: Eric "Erock" Calderone - Killer Instinct Meets Metal

@темы: PowerShell, Scripting

10:23 

Remote Desktop Connection Manager + Active Directory #2

Stance Dance

Скрипт доработан до полного функционала. Берет информацию о серверах из Active Directory, вносит ее в файл настроек RDCMan, затем убирает из этого файла настроек записи о серверах, которых уже нет в AD. Доработка напильником как всегда: указать путь к файлу настроек и задать критерии отбора серверов:

@музыка: Power of Melody - Poisoned Planet

@темы: Scripting, PowerShell

15:18 

Remote Desktop Connection Manager + Active Directory

Stance Dance

RDCMan попался мне на глаза довольно давно. Удобный инструмент для управления соединениями через RDP, плюс штампик "от производителя". Этот самый штампик и позволяет его использовать на рабочем месте. Да вот беда - эта программка ведет свой собственный список серверов, с Actove Directory никак не связанный. А это плохо, лениво каждый раз при вводе нового сервера добавлять его в лист RDCMan. Что же делать? Каким-то образом автоматизировать обновление списка, больше нечего.
Список серверов RDCMan хранит в специальном файле с расширением *.rdg (remote desktop group), который по своей сути является обычным XML-файлом. Вариантов его ведения может быть два - либо все серверы, добавленные в эту группу будут идти единым списком (именно это требуется и мне), либо же будут вручную разбиты по группам внутри списка. С ручной группировкой ничего не сделаешь - в AD нет сведений, по которым можно было бы серверы по группам раскидывать, а вот с простым списком можно и поковыряться. Powershell to the rescue!
Для начала заставим RDCMan создать файл группы серверов. Просто запускаем его и добавляем туда сервер-болванку, назначение которой - быть шаблоном для добавления остальных серверов. Попутно можно прописать туда общие настройки подключения - в 90% случаев все подключения проходят под одной и той же учеткой, с одинаковыми параметрами. После подготовки начинаем ваять сценарий синхронизации.
Первым делом в сценарии, который будет обновлять список серверов в RDCMan, поднимаем работу с Active Directory:

import-module activedirectory

Само собой, этот модуль уже должен быть установлен в системе.
Далее необходимо загрузить содержимое нашего файла в Powershell (нужно будет прописать путь к rdg-файлу

$doc="path-to-rdg-file"
$xml = New-Object XML
$xml.load($doc)

Следующий шаг - получение списка серверов из AD (необходимо подставить критерии отбора серверов):

$comps=get-adcomputer -filter 'insert-your-criteria'

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

foreach ($comp in $comps) {
$isExist=$False
foreach ($node in $xml.rdcman.file.server) {
if ($node.name -eq $comp.name) {$isExist=$True}
}

if ($isExist -eq $False) {
$clone = $xml.rdcman.file.server[0].clone()
$clone.name=$comp.name
$clone.displayName=$comp.name
$clone
$xml.rdcman.file.appendchild($clone)
}
$isExist=$False
}

В завершение - сохранение нашего файла RDCMan одной простой командой:

$xml.save($doc)

К чести RDCMаn стоит добавить, что сортировку серверов по алфавиту он выполнит автоматически при запуске (отключаемо). За это некоторые его ругают, но мне этот подход нравится.
Последним шагом будет удаление из списка RDCMan сервера-болванки.
Ну и пара слов по тому, каким образом можно использовать полученный сценарий. Лично мне по душе автоматический его запуск при логине в систему. Таким образом по завершении загрузки профиля список RDCMan'а уже будет актуализирован.
Что еще можно было бы добавить: обратную проверку. Если сервер перечислен в RDCMan, но его записи нет в AD - удалить его из RDCMan.

@темы: Scripting, PowerShell

11:47 

Drive letter in CMD

Stance Dance
Несмотря на мою нежную любовь к Powershell старый добрый CMD все же иногда нужен. Например, тогда, когда компьютер загружен с аварийного диска. Задача следующая - необходимо получить букву диска системного раздела. Всем известно, что во время загрузки с аварийных дисков буквы располагаются несколько в ином порядке, нежели обычно. Как же будем искать? Очень просто - по метке диска, которая была задана заранее - старая привычка маркировать раздел с ОС именно как "OS". Что ж, посмотрим, что у нас имеется. А имеется инструмент под названием wmic:
wmic logicaldisk
Эта команда покажет все логические диски, зарегистрированные в системе. А как бы нам отсечь ненужные разделы? Это можно сделать, отфильтровав вывод команды по полю volumename, а делается следующим образом:
wmic logicaldisk where volumename="OS"
В ответ получаем тонну сведений об интересующем нас логическом диске. Далее - выбираем из этого потока информации букву диска:
wmic logicaldisk where volumename="OS" get deviceID
Выводом в моем случае является вот это:

DeviceID
C:

Итак, почти добрались. Теперь бы еще избавиться от первой строки вывода. Не вопрос - воспользуемся "трубой" (конвейером) и командой поиска findstr:
wmic logicaldisk where volumename="OS" get deviceID | findstr :
Да, ищем символ двоеточия, который всегда присутствует рядом с именем диска. Получаем то, что нужно:
C:
Ну и самое вкусное - как бы теперь этот вывод утрамбовать в переменную. Именно та точка, где я снова и снова вспоминаю добрым словом Powershell, потому что там вывод можно просто присвоить некой переменной. В CMD нам это недоступно, поэтому будем обманывать через оператор FOR.

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

@музыка: Ryan Farish - Life in stereo (solarsoul remix)

@темы: Scripting

10:26 

Time Zones

Stance Dance
Казалось, что кошмар с переводом стрелок уже давно и прочно забыт. Ничего подобного:
Депутаты Государственной думы вернули россиянам постоянное зимнее время без сезонных переводов часов - Клац!

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

Поскольку во временной зоне Багдада нет перехода на зимнее/летнее время, а смещение как раз UTC+3, именно она нам и подойдет. Если по каким-то причинам не нравится Багдад, можно отослать ОС аж в Найроби, благо, параметры этой временной зоны отвечают всем требованиям :)


Как запустить эту команду на удаленных компьютерах - уже было написано немало, от PsExec, до PS Remoting.

@музыка: David & Diane Arkenstone - Night Flight

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

16:52 

System image and relocating user profiles at once...

Stance Dance
Итак, grand finale. Образ готов, осталось самое интересное - все же заставить пользовательские папки жить не на системном разделе. Как мы уже знаем, использовать файл ответов для этих целей нельзя. В сети гуляет второй метод - обман ОС при помощи файловой системы и симлинков, которые предоставляет файловая система. Идея проста - нужно загрузиться с любого LiveCD, умеющего работать с NTFS (самый простой вариант - с установочного диска Windows 7), перетащить каталог Users на нужный раздел, а на месте этого каталога на диске C: разместить симлинк, ведущий на истинное расположение папки профилей. Подводный камень в том, что встроенные средства Win 7 не умеют работать с junctions, которых в каждом профиле штук 15. А перенести их хотелось бы. Что ж, для этого подойдет программка fastcopy, синтаксис будет примерно таким (предполагая, что папки должны будут лежать на диске D:):
fastcopy /acl %systemdrive%\Users /to=D:
Это скопирует полностью каталог Users на диск D: с сохранением всех junctions и прав на каталог. Затем делаем сам симлинк:
mklink c:\Users d:\Users /J
Сказано - сделано. Каталог скопирован, симлинк - тоже, время запускать sysprep. После которого мы получаем... неработоспособную ОС, не способную пройти даже minisetup. Что за...?
Shift+F10 на экране с ошибкой, и смотрим, что у нас происходит. А происходит у нас следующее:

Проще говоря, sysprep взял наш созданный симлинк, ведущий на диск D:, и завернул его на самого себя! Тем самым порушив нашу установку.
В общем и целом, Windows очень активно сопротивляется любым попыткам переноса каталога Users. Стало быть, придется оставить его на месте, и работать с отдельными папками.
Теория. Все создаваемые учетные записи наследуют свои настройки от стандартного пользователя Default. В том числе и пути к папкам с контентом. Стало быть, как-то надо эти настройки изменить.
Если делать это из графического интерфейса руками, то выглядит это так: открываем regedit, в нем переходим на какой-нибудь куст, куда у нас есть права записи, и в него монтируем реестр из профиля Default, он лежит вот в этом файле:
%systemdrive%\Users\Default\ntuser.dat
После этого можем приступать к редактированию.
Нужные нам настройки хранятся по следующему пути (в моем случае профиль Default был примонтирован в ветку HKLM под именем DefaultProfile): HKLM\DefaultProfile\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
Практика. Поменять пути к тем папкам, которые требуется перенести, после чего записать изменения в этот файл реестра просто отмонтировав его соответствующей командой.
Если это оформить в виде скрипта (мы, администраторы, ведь очень ленивые люди, да?), то получится нечто вроде следующего:

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

Вышеуказанное можно оформить в виде *.cmd файла, разместив его в папке профиля пользователя Default. При этом он будет скопирован в каждый профиль каждого созданного пользователя. Осталось только обеспечить автоматический запуск этого сценария. Как сделать? Воспользуемся технологией RunOnce применительно к учетным записям. Для этого в тот код, который меняет пути к пользовательским каталогам, добавить инструкцию запуска кода очистки лишних папок (в данном примере скрипт очистки называется CleanUp.cmd и расположен в папке профиля Defaut):

На этом вроде все.

@темы: Scripting

16:16 

System Image part number next...

Stance Dance
Итак, задача, в общем-то, проста. Нужно подготовить образ системы на определенную модель ПК. Очень желательно, чтобы действий администратора было по минимуму. Образ на основе русского дистрибутива ОС Windows 7. Естественно, есть куча требований к состоянию ОС уже после развертывания образа (имя компьютера, состояние встроенных учетных записей, много чего). Естественно, нужно использовать sysprep.
На первый взгляд, ничего сложного. Подготавливаем исходный ПК, ставим на него ОС, все необходимые обновления, весь необходимый софт, проводим все настройки. После чего натравливаем на компьютер sysprep, захватываем образ. И потом уже этот образ раскидываем по рабочим станциям.
А теперь - детали, в которых кроется дьявол (который таки может плакать).
После выполнения sysprep /generalize все встроенные учетные записи будут переименованы. Да, они станут Администраторм и Гостем. Ладно, это можно обойти, в конце концов, после развертывания станции в любом случае будет исполняться настроечный сценарий, который учетные записи сделает такими, какими они и должны быть. Единственное, что остается неизменным - это пароли данных учеток, sysprep их не трогает. Уже проще.
Подводный камень номер два. После развертывания образа, на который был натравлен sysprep, первое, что появится на экране - это окно Windows Welcome. То самое окошко, где нужно задать и имя пользователя, и имя компьютера, а потом еще и политику обновлений, тип сети, часовой пояс, в общем - много всего. Лениво. Ладно, это тоже обходится при помощи файла ответов, о котором речь и пойдет.
Само по себе создание такого XML файла сложностей не представляет. Есть специальный инструмент, называется Windows System Image Manager. Как им пользоваться - есть подробнейшая справка. Скажу лишь, что возможности по настройке ОС он представляет поистине широчайшие.
Итак, файл ответов подготовлен, в него внесена информация о практически всех параметрах, которые нам мешают жить (то есть прерывают автоматическую установку). В том числе и создание временной учетной записи (без этого - к сожалению, никак). Следующий этап - каким-то образом заставить систему загружаться не под новосозданной учетной записью, а под той самой административной, что была задана еще на этапе установки исходной ОС. И вот тут начинается кавардак.
Административная учетная запись после sysprep блокируется. By default and hard-coded. Среди всего многообразия настраиваемых параметров в файле ответов разблокировки этой учетной записи как таковой нет. Как же быть? Ответ следующий: методов два. Один из них - выполнение специальной команды на этапе настройки specialize:
net user Администратор /active:yes
Второй - просто настроить автологин от имени этого самого администратора, в этом случае блокировка отменяется.
Отлично, убиваем двух зайцев сразу, тем более, что нам все равно автологин понадобится. И параметры автологина как раз настроить в файле ответов не проблема:
Как именно

После этого задаем все остальные нужные параметры и запускаем sysprep с указанием имени файла ответов (через графический интерфейс это сделать нельзя):
sysprep /oobe /generalize /shutdown /unattend:PATH_TO_XML_FILE
Когда компьютер выключится, снимаем образ, после чего загружаем его, чтобы посмотреть, что же у нас получилось.
Каково же было мое удивление, когда я увидел, что система попыталась выполнить автовход, но нарвалась на следующее: "При первом входе пользователь должен изменить пароль"
Что за ересь?! Учитывая, что у административной записи эта галка сроду не стоит, становится не совсем понятным, откуда она взялась.
Тут небольшое отступление. Поскольку дома у меня стоит английская ОС, то все имена учетных записей в файле ответов сначала были английскими. И все заработало. После переноса файла ответов в русскую ОС с заменой имен учетных записей на русские - получили вышеописанный результат. Вопрос - что пошло не так?
Конец отступления.
Предположив, что банально произошла какая-то ошибка во время развертывания ОС и применения файла ответов развернул образ еще раз. Нет, все так же - меняйте пароль. Хорошо, давай поменяем. Подтверждаю смену и вижу просто прекрасное: система пытается загрузиться не с помощью административной учетной записи, как это было указано в файле ответов, а с помощью новосозданной временной. Да, у нее флаг смены пароля установлен по умолчанию. Но как же так?
После установки и конфигурировании экрана Windows Welcome ОС сама пытается зайти под той учетной записью, которую найдет (кроме гостевой), и которая не будет неактивной. Получается, что запись администратора она не видит, или эта запись не разблокировалась. А не разблокированной эта учетная запись может остаться только в том случае, если в файле ответов почему-то она не указана в параметрах автовхода. Проверяю файл ответов, но загружать по-новой Windows SIM было лень. Тотал, выбрать файл, нажать F4...
Давайте разберемся. На дворе теперь уже 2014 год. Полное засилье Unicode. А Windows как работала весьма коряво с кодировками, так и продолжает работать.
В общем и целом, взору предстала картина убитого имени "Администратор", превращенного в набор непонятных символов. И это - при использовании официального инструмента от MS. ОК, в заголовке полученного XML файла четко написано:

Открываем его в режиме utf-8, правим убитое имя учетной записи, сохраняем, снова выполняем sysprep на восстановленной машине. И тут sysprep выдает вовсе парадоксальное - у вас нечитаемый файл ответов.
Опустим мои не самые лучшие мысли по этому поводу. Что же делать?
Почитав справку о стадиях настройки ОС после установки и пробежавшись по интернету, выяснил, что можно переименовать учетную запись еще до появления окна Windows Welcome, а это значит, что можно избавиться от русского имени. Все бы хорошо, но ведь для того, чтобы переименовать учетную запись, ее нужно выбрать, и выбирают чаще всего по имени, что опять приводит нас к использованию русских букв в файле ответов. А этого нужно избежать. И это возможно. Все компьютеры с Windows на борту назначают встроенной учетной записи администратора один и тот же SID. А это уже кое-что.
Итак, на стадии specialize даем запуск вот такой команды:

Эта команда найдет среди всех учеток лишь одну, и это будет именно встроенная учетная запись администратора. После чего команда переименует ее в удобный для нас англоязычный вариант.
Дальнейшее - тривиально. В параметрах автовхода указываем новое имя администраторской учетки, сохраняем файл ответов, выполняем sysprep, снимаем образ, загружаем. И да, получаем желаемый результат - однократный автовход под нужной нам учетной записью. Дальнейший запуск подготовленного скрипта окончательной настройки - и система готова.
Казалось бы, на этом все? Да как бы не так, потому что Windows все же не сдается. Сразу после автоматического входа под учетной записью Administrator ради интереса открыл список всех учеток на компьютере. Каково же было мое удивление, когда я увидел учетку "Администратор". Да, именно так, по-русски! Вот так и слышу мерзкое хихиканье из системного блока, мол, ты можешь как угодно извращаться с этой записью, но все равно будет по-моему! Но так и быть, за труды твои, неправедные, малость уступлю.

@музыка: Jaime Cristopherson - Metal Gear Rising: Revengeance OST - Montenergo

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

21:36 

User account properties

Stance Dance

Следующая подзадача в нашей эпопее - в образе есть дефолтная пользовательская учетка. После того, как образ развернется, этой учетке нужно поставить свойство User must change password at next logon. Естественно, по возможности опять же в powershell сделать.
Методов несколько. Чтобы не томить, привожу тот, что сработал в моем случае:

$username=%INSERT_ACCOUNT_NAME%
$user = [ADSI]"WinNT://$env:computername/$username,User"
$user.passwordexpired=1
$user.setinfo()

Код прост как две копейки. Получить от провайдера ADSI объект нашей учетки, поменять его свойство под названием "Пароль просрочен", подтвердить изменения. Все. Задача выполнена.
А вот в процессе написания выплыл интересный факт. Галка User must change password at next logon в интерфейсе свойств учетной записи связана с вот таким свойством: User Flags. Значение этого параметра вычисляемое и зависит от нескольких факторов. МСы в документации приводят полный список значений, которое это свойство может принять - Клац!
Ок, небольшой эксперимент. В свойствах учетной записи в графическом интерфейсе меняем все галки, кроме самой первой. Это как раз User must change password at next logon. А потом даем простые три строчки:

$username=%INSERT_ACCOUNT_NAME%
$user = [ADSI]"WinNT://$env:computername/$usenamer,User"
$user | fl *

И наблюдаем, что параметр UserFlags принял значение 8389121. Закономерный вопрос - как так?! Ответить на него еще только предстоит. А пока - добиваем в скрипт окончательной настройки системы после развертывания полученный ранее блок команд, и наслаждаемся результатом.

@музыка: Laliya - Just like river

@темы: PowerShell, Scripting

23:55 

Imagex - специально для "наркоманов"

Stance Dance
Пожалуй, ни одна из систем снятия образов дисков не заставляла специально для нее писать хоть сколько нибудь строчек кода. Но поскольку ImageX - консольное приложение, без скриптов не обойтись, с другой стороны - это новое знание, то, за чем я и охочусь.
Итак, что нужно? Есть ноутбук. На нем уже установлена Windows 7 с кучей дополнительных программ от известной конторы с двухбуквенным названием. Задача следующая - снести все лишнее, установить требуемое ПО, провести базовую настройку параметров, после чего снять образ системы с таким расчетом, чтобы этот образ можно было развернуть на порядочном числе таких же ноутбуков. В общем, задача тривиальная. Нетривиально тут другое - режим работы жесткого диска. В наличии стандартный HDD и к нему в пару SSD небольшого размера, работающий как кэш-диск. И вот с этим-то у большинства систем подготовки образов возникли проблемы. Кто не смог правильно опознать контроллер жестких дисков (типичная проблема, надо признать), кто-то сделал образ, но при попытке его развернуть получаем систему, уходящую в BSOD, или еще интереснее, потерявшую загрузчик. В общем, неважно дела обстоят в датском королевстве. А поскольку ImageX был известен, но еще ни разу в жизни не был опробован, почему бы не дать ему шанс.
ImageX работает в окружении WinPE. Следовательно, если WinPE сможет увидеть HDD, то это сможет сделать и ImageX, ему будет плевать на контроллеры, контроллерами будет заниматься WinPE, а он это умеет. Это плюс, потому что одной проблемой меньше. Далее - ImageX является детищем MS, стало быть, можно надеяться на почти безглючную работу (полностью безглючной не бывает в принципе). Ну и третье - Windows AIK, частью которого являются WinPE и ImageX, можно абсолютно бесплатно загрузить с сайта MS и пользоваться в свое удовольствие. Это тоже немаловажно.
Итак, все стащено, подготовлен загрузочный образ, в него внедрен ImageX. Берем исходный ноутбук и начинаем прикидывать, что и как. Общими усилиями приходим к выводу, что на свежеустановленной ОС жесткие диски работают в обычном режиме: HDD принимает на себя всю нагрузку, а SSD остается в стороне и ничего не делает. Режим кэширования нужно включать руками. Это хорошо. Потому что кэширование не будет мешать на этапе снятия образа. Сказано - сделано. Кэширование выключено, ОС установлена, драйверы установлены. Заодно разбили жесткий диск ноутбука так, как требовалось (нужно несколько разделов). Рабочее ПО пока не накатываем, любопытно, как же поведет себя образ системы в принципе. Последний шаг подготовки исходного ПК - "запечатывание":

C:\Windows\system32\sysprep\sysprep /oobe /generalize /shutdown

Все. Система потушена и подготовлена к снятию образа. Теперь на сцену выходит WinPE.
Сама по себе загрузка с этого диска не отличается от загрузки с обычного дистрибутива Windows, только их всего интерфейса мы получим обычную консоль cmd.exe. Большего и не нужно. До загрузки неплохо было бы подключить флешку или внешний HDD, чтобы было куда образ положить.
Теперь начинаем разбираться, как же работает ImageX. Вообще лучше для этого прочесть соответствующую страницу на Technet - там все команды расписаны весьма подробно. Одно только омрачает: ImageX в своей работе полагается на буквы дисков, а расставляются они весьма забавно. В итоге, чтобы узнать, какие буквы отвечают за нужные нам разделы, можно воспользоваться программой DiskPart, она, кстати, нам очень пригодится на этапе развертывания образа. Чтобы увидеть буквы дисков, нужно зайти в сам DiskPart, набрав это слово в командной строке, а в ответ на приглашение самого DiskPart ввести List Volume. DiskPart покажет все имеющиеся тома. Запоминаем те, что нам нужны.
В моем случае раскладка была такой:
Диск С - зарезервированный системой раздел, где хранится информация о загрузчике.
Диск D - это тот диск, где установлена сама ОС (в Windows изсестный как C:)
Диск Е - дополнительный диск, созданный с учетом необходимости (в Windows виден как диск D:)
Что ж, буквы определены, можно натравливать на диски сам ImageX.
Поскольку ImageX не умеет снимать данные со всех разделов, придется вызвать эту программу трижды (по числу разделов), меняя параметры. Получилось вот так:

Параметры таковы:
/capture - захват образа раздела и помещение его в создаваемый файл образа.
/append - захват образа раздела и добавление его в уже существующий файл образа.
/boot - этот ключ дает понять, что мы захватываем загрузочный раздел (в Windows в диспетчере дисков он маркируется как Boot)
G:\backup.wim - собственно расположение файла образа
Подпись в кавычках - подпись образа раздела в файле образа. так можно будет определить, где какой раздел.
В общем и целом, со снятием образа проблем не возникло, ImageX отработал как часы. Теперь тест - как образ развернется. В качестве теста используем эту же машину, вычистив ее жесткий диск. Вот тут на сцену опять выйдет DiskPart, причем в режиме исполнения сценариев.
Сценарий таков:

Что он сделает? Выберет диск с номером 0 (наш HDD и есть нулевой), вытрет на нем все разделы и создаст их заново. Три штуки с требуемыми объемами. Буквы им будут присвоены с конца алфавита, чтобы не было конфликтов с имеющимися на данный момент. Буква X пропущена, потому что она будет занята виртуальным диском (его создаст сам WinPE в процессе загрузки).
Как добиться от DiskPart работы в режиме скрипта? Очень просто:

DiskPart /s sсript.txt, где sсript.txt - собственно файл, в котором содержатся команды для DiskPart.

Ну а после того, как все необходимые разделы будут подготовлены, на сцене снова появится ImageX в режиме применения файла образа:

В принципе, тут все примитивно. Берется файл образа, их него извлекается первый созданный образ раздела и применяется к диску z:, затем второй образ накатывается на диск y:, а третий - на диск w:
После завершения развертывания образа идет самый интригующий момент. Запустится или нет. Запустилось. Система послушно ушла в OOBE режим, что и требовалось по условиям задачи. Метод работает, следующий этап - подготовка полного эталонного ноутбука и снятие образа уже с него с переносом на другой ноутбук. Но эту траву будем курить уже после выходных.
При известном желании можно заскриптовать весь этот процесс. Собственно, развертывание образа на ноутбуки сейчас и реализовано в виде cmd-файла. Создание же образа оформлять в виде скрипта показалось излишним, это однократная процедура.

@музыка: Oysten Sevag - The door is open

@темы: Scripting

19:25 

Download KVRT in Powershell

Stance Dance

Когда-то давно довелось мне написать скрипт автоматической загрузки Kaspersky Virus Removal Tool. Как показало время - запись та была достаточно популярной. Как и сам KVRT. Поскольку же прогресс не стоит на месте, и многие все же переходят на ОС Windows 7 и выше, специально для них (и для себя любимого в их числе) переработал тот сценарий, переписав его в Powershell. Вон он:

Download KVRT.ps1

Обработка напильником стандартная: в строке $folder = "d:\KVRT" прописать имя того каталога, куда будет складываться загружаемый файл.
ВНИМАНИЕ! Содержимое каталога, указанного в переменной $folder, будет удалено в процессе выполнения этого сценария. Это сделано специально, исходя из собственных нужд. Если очистка каталога нежелательна, нужно закомментировать строку remove-item $folder\*.* при помощи символа # (или вообще удалить ее).
Ну а о том, как можно Powershell-скрипт запускать по расписанию, в сети материала вагоны )

@музыка: Adrian von Ziegler - The Stormbringer

@темы: Viruses and Spam, Scripting, PowerShell, Kaspersky Lab

12:56 

Parse and sort

Stance Dance

После развертывания MDT, которым сейчас вовсю пользуются ребята из службы поддержки, возникла одна проблема. Большая она или нет - это с какой стороны взглянуть. Суть в следующем - когда рабочая станция получает образ ОС и вводится в домен при помощи MDT, она попадает в базовую OU Computers. В то же время у нас AD разбита по отделениями и филиалам, на каждый филиал своя OU. И теперь нужно вручную все эти компьютеры раскидать по различным OU. Лениво. Впрочем, так скажет любой администратор. Что же делать?
У каждого отделения свой диапазон IP адресов. Все IP адреса есть в DNS. Стало быть, можно определить, какой компьютер из базовой OU куда должен улететь. Остается лишь получить IP адрес компьютера и сказать скрипту, чтобы он принял решение о переносе компьютера в нужную OU именно на основании полученного адреса. Но как это сделать? Стандартная команда nslookup выдаст нам море лишней информации - имя контроллера домена, его адрес, имя интересующего нас хоста... Более того, все это будет в нескольких строках. Значит, придется парсить эти строки, ничего не поделать. Снова и снова берем в руки Powershell и начинаем размышлять.
Утрамбовать вывод стандартного nslookup в какую-либо переменную труда не составляет:
$var = nslookup hostname
Дальше пропишем небольшую модель нашей сети. Итак, пусть диапазоны адресов, которые будут использоваться, выглядят так:
Главный офис - 10.10.1.1 - 10.10.6.255
Филиал 1 - 10.20.1.0/24
Филиал 2 - 10.20.2.0/24
Филиал 3 - 10.20.3.0/24
...

В главном офисе стоят все серверы, их подсеть - 10.10.1.1-10.10.1.254. Среди них и сидит наш DNS сервер, который будет отдавать информацию по nslookup. Диапазон адресов рабочих станций в центральном офисе - 10.10.3.1 - 10.10.6.255.
Стало быть, когда будем парсить вывод nslookup, нам нужно будет игнорировать в выводе адрес вида 10.10.1.x - адрес нашего DNS - он бесполезен.
Стандартный вывод nslookup будет выглядеть следующим образом:
c:\> nslookup hostname

server: DNS-fqdn
Address: DNS-ip

name: hostname
Address: hostname-ip
Последняя строка может приять вид Addresses: hostname-ip1, hostname-ip2 если адресов больше одного.
Итак, нас будет интересовать последняя строка. Для построчного анализа можно использовать следующую конструкицю
foreach ($line in $var) { sсript-block }
В переменную $line будут поочередно заноситься все строки, хранящиеся в многострочной переменной $var, и уже переменная $line будет подвергаться анализу, что нам и нужно. Основной вопрос - как проверять? Тут на помощь придет трава (иначе и не скажешь) под названием регулярные выражения. Выглядеть в реализации Powershell это будет следующим образом:

Под CO тут понимается центральный офис (он же главный офис).
На этом самая заковыристая часть скрипта написана. Остается только сделать выборку компьютеров из базовой OU Computers, прописать механизм переноса записи компьютера между OU, да перечислить все возможные блоки в цикле foreach ($line in $var) { }. Все это уже тривиально.
Ну и попутно придется курить руководства по MDT в плане возможности выбора OU, куда компьютер будет сразу прописываться.

@музыка: RA - Creation of Tefnet

@темы: Scripting, PowerShell

16:10 

Windows Distribution Point #2

Stance Dance

В предыдущей записи было рассказано, как можно подготовить пачку обновлений для интеграции их в дистрибутив ОС. Следующий шаг - непосредственно внедрение. Делается просто - вызываем интересующий нас файл с параметром /integrate, в котором прописываем путь к дистрибутиву. Само собой, что дистрибутив нужно скопировать с компакт-диска, ведь на сам компакт просто так ничего не запишешь. Ну и само собой - язык ОС должен совпадать с языком обновлений, иначе интеграция не пройдет.
Хорошо, ну один файл, ну два, ну три... А когда их нужно под сотню обработать? Не руками же все это каждый раз прописывать. Верно, не руками. Снова запускаем ISE и пишем там следующее:

Где E:\WinXP-Update-Pack - имя каталога с файлами обновлений, d:\winxp - каталог с файлами дистрибутива Windows XP SP3.
Скрипт сначала прочитает список файлов обновлений, а потом будет обрабатывать их по одному, попутно выводя на экран сообщение о том, что именно в данный момент встраивается в дистрибутив. Процесс довольно долгий, можно выпить не одну чашку чая/кофе. В моем случае пришлось на это положить час, завалившись на диван с прелестной книгой.
По окончании процесса нужно будет лишь из каталога d:\winxp (с моем случае) собрать ISO файл, который уже можно использовать для установки ОС.
На первый взгляд - все просто. Но - как бы не так. При попытке установки Windows XP из полученного дистрибутива получаем странное:
lsass.exe - недостаточно квот на виртуальную память или файл подкачки для завершения требуемой операции.
Как подсказывает всемирный разум - такое поведение наблюдается при интеграции в дистрибутив, помимо всего прочего, еще и Internet Explorer/Windows Media Player старших версий. Убрал файлы этих обновлений из каталога перед интеграцией - проблема решилась. Ладно, эти продукты можно и через WSUS ставить.

@музыка: Poets of the Fall - May be tomorrow is a better day

@темы: PowerShell, Scripting

15:55 

Windows Distribution Point.

Stance Dance

Идея единой точки распространения дистрибутива Windows на работе занимает мой мозг уже давно. В принципе, этот сервис уже поднят, настроен и работает. Связка WDS + MDT 2010 отработала просто прекрасно, стоило потратить пару дней на "вкуривание" процесса настройки MDT. Но остался нерешенным один вопрос - что делать с обновлениями ОС после установки? Да, поднят и работает WSUS, но сам процесс установки, когда машина тащит и натягивает на себя больше сотни обновок, просто очень долог. Остается только один вариант - интеграция обновлений непосредственно в дистрибутив. После установки ОС уже будет пропатчена по самое не могу. Идея хорошая, но где взять эти обновления? Не руками же с сайта Windows Update вытаскивать, хотя и была такая идея.
Сначала попробовал вынуть из из WSUS при помощи новоразвернутой машины. Да, вынуть их удалось, но уже в распакованном виде. Не пойдет, потому что заветный ключ /integrate применяется только к упакованным обновлениям, а как их паковать таким образом, MS, конечно же, не объясняет, ибо зачем?
Гугл, запрос, курение результатов. Результатом стала следующая ссылка:
support.microsoft.com/kb/913086 - Security updates are available on ISO-9660 DVD5 image files from the Microsoft Download Center
Да, вы не ошиблись. Все апдейты доступны в виде ISO образов. Для всех систем. Трафика, конечно, ушло безумно много - 90 Гб, зато теперь есть все необходимое.
Только вот одна проблема. 56 образов, если считать от месяца выпуска SP3 для Windows XP (меня интересует этот дистрибутив). Каждый из них нужно распотрошить, выбрать оттуда каталог с нужной версией, архитектурой, языком, вытащить оттуда файлы и сложить в отдельный каталог. Ужас. Что же делать? Окидываем взглядом систему, понимаем, что в ней есть следующие компоненты: Daemon Tools, Powershell, ISE. Большего и желать нельзя. Ну и справка от Daemon Tools, конечно же.
Итак, идея в том, чтобы заставить Powershell-скрипт извлекать из образов нужные файлы. Структура каталогов внутри каждого образа известна - номер Knowledge Base, версия ОС, архитектура, язык, например, DriveLetter:\2723135\WindowsXP\x86\*.exe
Заставить извлекать файлы по таким путям - дело нехитрое. А вот что делать с процессом монтирования образов? Тут-то на помощь и придет Daemon Tools. Эта широко известная программка способна работать не только в обычном графическом режиме, но и через командную строку. Ее ключи подробнейшим образом расписаны во встроенной справке, хотя и там не обошлось без накладки, ее я выделю позже.
Теперь перечислим, что у нас имеется (применительно к моей системе):
Файлы всех ISO образов лежат в папке D:\Temp\Архивы
Складывать все обновления мы будем на диск E: в соотвествующие папки.
Daemon Tools установлен в стандартный каталог C:\Program Files (x86)\DAEMON Tools Lite.
Виртуальный диск, в который монтируются файлы-образы, имеет букву G:
Поехали:

В принципе, код не сложен. Отдельно хотелось бы остановиться на паре моментов.
Первый - строка $args = "-mount 0,$iso. Именно здесь задаются ключи запуска Daemon Tools. И именно здесть есть небольшая накладка в справке самой DT. В ней указано, что среди параметров необходимо указывать тип драйва, в который мы стараемся монтировать файл-образ. На практике попытка указать тип приводит к ошибке, поэтому тип драйва просто опущен. А должно было быть вот так: $args = "-mount scsi,0,$iso".
Ну а второй момент - искуственная задержка start-sleep 5 - самой Daemon Tools требуется некоторое время на монтирование образа.
Ради интереса в код ввел вывод времени начала и окончания выполнения. Выяснил, что весь скрипт отрабатывает 5 минут или около того. Представляю, сколько времени я бы все эти действия выполнял руками...
Может возникнуть вопрос - а что за блоки, связанные с обновлениями Win7 и язык такой Neu. Ответ на первую часть вопроса прост - в рамках этого же скрипта еще и для семерки файлы обновлений вытащим. А вот что за локаль такая - я и сам не знаю. Все обновления Win7 идут только в ней. В папках Rus для семерки не оказалось ни одного файла, только в Neu.
... И почему нативная поддержка ISO в Windows появилась только в Win 8...

@музыка: Poets of the Fall - May be tomorrow is a better day

@темы: PowerShell, Scripting

15:49 

Users in groups...

Stance Dance

Недавно обнаружил странную особенность в поведении скрипта обработки учеток уволенных сотрудников. Предполагается, что учетная запись будет вышвырнута из всех групп, кроме базовой Domain Users, после чего заблокирована. Странность в том, что на одних учетках эта процедура отрабатывает на ура (в том числе и на моей тестовой), а на других - на первый взгляд не работает вообще. Вот как это реализовано:
(get-qaduser $user).memberof | Get-QADGroup | where {$_.name -ne "domain users"} | Remove-QADGroupMember -member $user
Начинаем разбор полетов. Берем учетную запись, уже отключенную ранее, видим, что в свойствах AD групп там перечислено довольно много. Понятно, скрипт не отработал. Загоняем данные этой учетки в переменную $user, запускаем строку на исполнение, и видим прекрасное:
Remove-QADGroupMember : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
Уже интереснее. В голове тут же формируется мысль о том, что сотрудник этот сидит не только в группах нашего домена, но и соседнего, а в свойствах учетки через ADUC такие группы не видны. Что ж, даем следующее:
$col = (get-qaduser $user).memberof | Get-QADGroup | where {$_.name -ne "domain users"}
$col

Так и есть. Кучка групп из других доменов. Скрипт натыкался на такую группу, получал отлуп и прекращал обработку всех групп у этой учетки, переходя к остальным процедурам. Надо исправить:
$colGroups = (get-qaduser $user).memberof | Get-QADGroup | where {$_.name -ne "domain users"}
foreach ($group in $colGroups) { Remove-qadgroupmember -identity $group -member (get-qaduser $user) }

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

@музыка: Medwyn Goodall - Snows of Kilimanjaro

@темы: PowerShell, Scripting

18:08 

DFSR Backlogged files

Stance Dance

Что такое backlog? Это очередь файлов, которые еще не были реплицированы при помощи механизма DFSR. Само по себе наличие этой очереди еще не говорит о проблемах, но вот если при проверке выясняется, что эта очередь постоянно растет, стоит задуматься, а что идет неправильно. Но для того, чтобы иметь представление о динамике очереди, ее нужно наблюдать.
В Windows 2003 R2/2008/2008 R2 есть очень хорошая оснастка, через которую DFSR и управляется. Но есть у нее один недостаток: все операции с отчетами, которые там можно сделать, выполняются однократно. А хотелось бы автоматизации. Что ж, как всегда, консоль наш лучший друг.
Скрипт будет состоять из следующих логических блоков:
1. Сбор информации об интересующей нас группе репликации в специальный файл
2. Отсылка собранной информации (то есть выходного файла) на почтовый ящик администратора файлового сервера.
Основной инструмент, который нам поможет - консольная утилита dfsrdiag.
Сам сценарий выглядит следующим образом:

# get statistics
dfsrdiag backlog /receivingmember:%RECEIVING-SIDE-FQDN% /sendingMember:%SENDING-SIDE-FQDN% /RGName:%REPLICATION-GROUP-NAME% /RFName:%REPLICATED-FOLDER-NAME% /v > c:\DFSR-backlogged.txt

# send report to administrator
$filename = "c:\DFSR-backlogged.txt"
$smtpServer = %SMTP-SERVER-NAME%

$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mail.Attachment($filename)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)

$msg.From = %SENDER-ADDRESS%
$msg.To.Add(%RECIPIENT-ADDRESS%)
$msg.Subject = "Backlog Report"
$msg.Body = "DFSR Backlogged files"
$msg.Attachments.Add($att)

$smtp.Send($msg)
exit

Масштабирование скрипта очень простое - добавляем столько блоков get statistics, сколько групп репликации нам нужно просмотреть, заканчивая их перенаправлением в файл с дозаписью в конец: >> c:\DFSR-backlogged.txt

Дальнейшее - тривиально: запуск этого powershell-скрипта через Task Scheduler на файловом сервере, и статистика будет приходить автоматом. Что и требовалось.

@музыка: Davol - Nautikos

@темы: PowerShell, Scripting

20:52 

Призраки в рассылках

Stance Dance

Упало в ящик письмо от нашего любимого отдела травокуров (маркетинг, то есть). Мол, сделали рассылку, а назад почему-то вернулся список людей, которым она не дошла. И более того, все эти люди - уже давным давно числятся, как уволенные. В принципе, не дошла, и ладно, но хотелось бы, чтобы их в рассылке вообще не было.
И то верно, зачем нагружать почтовик лишний раз. Запрашиваю имя той рассылки, вспоминая, что при увольнении у нас учетка удаляется из всех групп. Как групп безопасности, так и групп распространения. Тем временем приходит ответ от травокуров с именем той рассылки. Читаю и понимаю, что это динамическая группа, и простым удалением из наших групп распространения тут дело не обойдется. И более того, группа создана в Москве.
Пишу московским админам, мол, так и так - на основании каких критериев формируется данная рассылка. Ответ пришел, из которого стало ясно, что одна из московских же систем определенным учеткам развешивает расширенные атрибуты (extensionAttributeN, где N - индекс от 1 до 15). На основании их-то и формируется список рассылки.
Прелестно. Хотите сказать, что теперь мне придется руками обнулить эти атрибуты у всех уволенных учеток? Нет, так дела не делаются. Консоль в зубы и вперед.

foreach ($user in (Get-QADUser -SearchRoot "INSERT_ROOT_OF_SEARCH" -SizeLimit 0)) {
foreach ($index in 1..15) {
set-QADUser $user -oa @{"extensionattribute$index"=""}
}
}

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

@музыка: Joel Kanning - Sedona's Calling

@темы: PowerShell, Scripting

16:20 

Удаление старых компьютеров

Stance Dance

Возможно, кому-то этот небольшой скрипт будет полезен при чистке рабочего AD и DNS. Суть в следующем: при удалении объекта из каталога AD автоматического удаления записей об этом объекте из DNS не произойдет. Верно и обратное - сотрем запись из зон DNS, останется запись в AD, все нужно делать руками. А хочется автоматизации, хоть какой-то.
Прекрасно известно, что для очистки записей DNS существует механизм Aging/Scavenging, но не всегда им можно воспользоваться. Итак, сам скрипт ниже:

$DNSServerName = "servername"
$DNSDomainName = "example.com"
$hostname = (Read-Host -Prompt "Введите имя машины:")
$FQDN = $hostname + "." + $DNSDomainName
get-qadcomputer -identity $hostname | Remove-QADObject
Get-WmiObject -ComputerName $DNSServerName -Namespace 'root\MicrosoftDNS' -Class MicrosoftDNS_AType | where {$_.textRepresentation -like "$FQDN*"} | Remove-WmiObject
Get-WmiObject -ComputerName $DNSServerName -Namespace 'root\MicrosoftDNS' -Class MicrosoftDNS_PTRType | where {$_.textRepresentation -like "*$FQDN."} | Remove-WmiObject

Обработка напильником очевидна: нужно указать имя DNS-сервера, указать имя нашего домена, а в приглашении вводим имя той машины, информацию о которой требуется удалить из наших AD и DNS. Получив имя, скрипт сначала находит эту машину в базе AD и стирает ее командой Remove-QADObject.
Следующий этап - чистка записей DNS. Сначала скрипт пробегает по A-записям (прямая зона), вытаскивает нужную (критерием выступает FQDN нашей машины) и удаляет ее, затем та же операция выполняется применительно к PTR-записи (обратная зона).

@музыка: Joel Kanning - Sedona's Calling

@темы: Scripting, PowerShell

18:14 

Oneliners #6 - Archiving

Stance Dance

Продолжая опупею с уборкой всякого мусора...
Все домашние папки уволенных сотрудников перемещаются на резервную файлопомойку, где и живут. Обращений к этим файлам нет, но хранить мы их обязаны. Возникла мысль утрамбовать все это на кассету ленточки. Сказано, сделано, тем более, что ленточка имеется - HP StorageWorks Ultrium 448.
300 Гб данных. В принципе, если все данные будут аппаратно сжаты с коэффициентом 2:1 при архивировании - на одну кассету влезут. А кассета как раз одна (Ultrium 2). Более старшие модели кассет эта ленточка не понимает.
Тестовый прогон показал, что не все не влезет. Значит, надо паковать, предварительно выкинув всякий плохо сжимаемый мусор. Mp3, Avi, Vob, Ost (да, там добра полно), но мусор уже был выкинут заранее. Остается только упаковать.
Инструментарий - Powershell + используемый на предприятии 7zip. Однострочник получается следующим:
$dirs=get-childitem < HOMES-PATH >;foreach ($dir in $dirs) {$cmd="C:\Progra~1\7-Zip\7z.exe a -r < PATH-TO-ARCHIVE-FOLDER >\$dir.7z < HOMES-PATH >\$dir\*.*";invoke-expression $cmd}

Разберем по складам.
Сначала в коллекцию $dirs выбираем все наши домашние папочки. Затем для каждой папки из этой коллекции, имя которой заносится в переменную $dir, формируем команду вызова внешней программы с таким набором параметров, которые обеспечивают архивацию всего, что в этой папке есть, в архив с именем, совпадающем с именем папки. Лежать этот архив должен по пути, задаваемом блоком < PATH-TO-ARCHIVE-FOLDER >.
Финальная часть, invoke-expression $cmd, просто вызывает заранее сформированную в переменной $cmd команду.
Что имеем? Имеем набор архивов, по одному на каждый домашний каталог. Каков будет выигрыш по занимаемому объему - покажет время, выполняться этот скрипт собирается долго, но спешить мне особо некуда.

@музыка: Galactic Warriors - Return to Atlantis

@темы: PowerShell, Scripting

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

главная