sergey vasin

The IT blog

PowerShell Workflows: Перезагрузка компьютера – Hey, Scripting Guy! Blog

leave a comment »

Резюме: Microsoft PowerShell MVP Richard Siddaway продолжает свою серию статей о рабочих процессах Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson на связи. Сегодня я публикую пятую часть в серии статей о рабочих процессах Windows PowerShell за авторством Windows PowerShell MVP и Honorary Scripting Guy Richard Siddaway.

Заметка: Первая статья, PowerShell Workflows: Основы рассказывает об основных концепциях рабочих процессов. Вторая, PowerShell Workflows: Ограничения, рассматривает ограничения, с которыми вы можете столкнуться при написании рабочих процессов. Третья статья, PowerShell Workflows: Вложения, рассказывает о вложении рабочих процессов. В четвертой статье, PowerShell Workflows – Механизм заданий, рассказывается о запуске рабочих процессов в качестве заданий Windows PowerShell. Перед тем как читать эту статью, вам стоит ознакомиться с предыдущими.

Richard Siddaway написал несколько гостевых постов, кроме этого он является автором двух книг по Windows PowerShell. Последняя его книга, PowerShell in Depth написана в соавторстве двумя другими MVP – Don Jones и Jeffrey Hicks.

Итак, Ричард.

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

Перезагрузка компьютера может потребоваться, например, в следующих случаях:

  • Изменение имени компьютера
  • Добавление в домен или удаление из него
  • Установка программного обеспечения или обновлений
  • Запуск Chkdsk на системном диске

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

Давайте рассмотрим следующие сценарии:

1. Перезагрузка компьютера, к которому удаленно подключается рабочий процесс.

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

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

Первый случай является наиболее простым, поэтому с него и начнем.

Перезагрузка удаленного компьютера

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

workflow test-restart {

param ([string[]]$computernames)

foreach -parallel ($computer in $computernames) {

Get-WmiObject -Class Win32_ComputerSystem -PSComputerName $computer

Get-WmiObject -Class Win32_OperatingSystem -PSComputerName $computer

}

}

Все, что он делает – это получает информацию о компьютере и операционной системе посредством вызовов WMI. Так как мы используем командлеты WMI вместо CIM, нам не важно, работает ли WSMAN на всех машинах. Для тестирования мы используем два удаленных компьютера:

W12standard – Windows Server 2012 (Windows PowerShell 3.0)

WebR201 – Windows Server 2008 R2 (Windows PowerShell 2.0)

Рабочий процесс запускается следующим образом:

PS> test-restart -computernames w12standard, webr201

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

Рабочий процесс параллельно подключается к удаленным компьютерам, на каждом выполняя последовательность WMI запросов. Команды блока foreach выполняются последовательно, но запуск их на разных компьютерах происходит параллельно.

Теперь добавим в рабочий процесс команду перезагрузки компьютера.

workflow test-restart {

param ([string[]]$computernames)

foreach -parallel ($computer in $computernames) {

Get-WmiObject -Class Win32_ComputerSystem -PSComputerName $computer

Restart-Computer -Wait -PSComputerName $computer

Get-WmiObject -Class Win32_OperatingSystem -PSComputerName $computer

}

}

Перезагрузка удаленных компьютеров инициируется в строке:

Restart-Computer -Wait -PSComputerName $computer

Обратите внимание на параметр –Wait. Его наличие приводит к тому, что рабочий процесс ожидает пока удаленный компьютер перезагрузится, прежде чем продолжить выполнение команд.

Если вы запустите рабочий процесс из консоли Windows PowerShell или из Windows PowerShell Integrated Scripting Environment (ISE), вы увидите индикатор выполнения, указывающий стадии перезагрузки:

  • Waiting for restart to begin
  • Verifying computer has restarted
  • Waiting for WMI connectivity
  • Waiting for Windows PowerShell connectivity
  • Waiting for WinRM connectivity

В моем случае Windows Server 2012 перезагружается гораздо быстрее, чем Windows Server 2008 R2.

В статье TechNet “Restarting the Computer in a Workflow” можно найти следующий код:

Restart-Computer -Wait -PSConnectionRetryCount 4 -PSConnectionRetryInterval 5

Заметка: Параметры PSConnectionRetryCount и PSConnectionRetryInterval не распознаются как параметры рабочего процесса.

Вы также можете запустить рабочий процесс в качестве задания Windows PowerShell:

PS> test-restart -computernames w12standard, webr201 -AsJob

Id Name PSJobTypeName State HasMoreData Location

— —- ————- —— ———— ———

25 Job25 PSWorkflowJob Running True localhost

После того, как задание завершит свое выполнение, вы можете просмотреть полученные данные. Однако, вы получите только данные WMI, сообщения о состоянии перезагрузки выведены не будут.

Перезагрузка компьютера, на котором запущен рабочий процесс

Здесь у нас есть два варианта:

  • Перезапуск рабочего процесса вручную
  • Перезапуск рабочего процесса автоматически

Давайте начнем с ручного перезапуска.

Перезапуск рабочего процесса вручную

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

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

Здесь мы используем активность Rename-Computer. Переименование компьютера – это одно из действий, требующих перезагрузки компьютера.

workflow rename-localsystem {

param (

[string]$newname

)

Rename-Computer -Newname $newname -Force -Passthru

Restart-Computer -Wait

Get-CimInstance -ClassName Win32_ComputerSystem |

Select-Object -ExpandProperty Name |

Set-Content -Path «C:\Scripts\$newname.txt»

}

Рабочий процесс получает новое имя компьютера в качестве параметра. Он переименовывает компьютер и затем вызывает активность Restart-Computer с параметром –Wait. После перезагрузки, рабочий процесс получает текущее имя компьютера и сохраняет его в текстовом файле. Имя файла соответствует новому имени компьютера.

Для начала получим текущее имя компьютера. В нашем случае – это “TEST1NOJOBPARAM”.

PS C:\scripts> $env:COMPUTERNAME

TEST1NOJOBPARAM

PS C:\scripts> rename-localsystem -newname W12SUS

Затем мы запустим рабочий процесс, указав в качестве параметра новое имя компьютера. Заметьте, что мы не использовали параметр –AsJob. Рабочий процесс изменяет имя и компьютер перезагружается.

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

PS C:\scripts> ls

Directory: C:\scripts

Mode LastWriteTime Length Name

—- ————- —— —-

d—- 14/12/2012 18:45 Setup

-a— 02/01/2013 11:58 280 rename-localsystem.ps1

Как видите, файла не существует. Также в списке задач присутствует задача в состоянии Suspended.

PS C:\scripts> Import-Module PSWorkflow

PS C:\scripts> Get-Job | Format-Table -AutoSize

Id Name PSJobTypeName State HasMoreData Location Command

— —- ————- —— ———— ——— ——-

3 Job2 PSWorkflowJob Suspended True localhost rename-localsystem

Возобновим задачу. Она завершит свое выполнение и создаст текстовый файл. В качестве завершающей проверки, мы получим значение переменной среды – COMPUTERNAME.

PS C:\scripts> ls

Directory: C:\scripts

Mode LastWriteTime Length Name

—- ————- —— —-

d—- 14/12/2012 18:45 Setup

-a— 02/01/2013 11:58 280 rename-localsystem.ps1

-a— 02/01/2013 12:24 8 W12SUS.txt

PS C:\scripts> $env:COMPUTERNAME

W12SUS

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

Рассмотрим пример:

workflow add-localsystemtodomain{

param (

$domcred,

[string]$ipv4address

)

$index = Get-NetIPInterface -AddressFamily IPv4 -Dhcp Enabled |

Select-Object -ExpandProperty ifIndex

New-NetIPAddress -InterfaceIndex $index -AddressFamily IPv4 `

-IPAddress $ipv4address -PrefixLength 24

Set-DnsClientServerAddress -InterfaceIndex $index -ServerAddresses «10.10.54.201»

Set-DnsClient -InterfaceIndex $index -ConnectionSpecificSuffix «manticore.org»

Add-Computer -Credential $domcred -DomainName Manticore `

-OUPath «OU=Security Servers,OU=Servers,DC=Manticore,DC=org» -Force

Restart-Computer

}

## remove relicit jobs

Get-Job |

where PSJobTypeName -eq «PSWorkflowJob» |

Remove-Job

$cred = Get-Credential

add-localsystemtodomain -domcred $cred -ipv4address «10.10.54.170» -JobName AddToDomain

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

Скрипт удаляет все существующие задачи, связанные с рабочими процессами, запрашивает учетные данные для добавления компьютера в домен и запускает рабочий процесс. Так как для активности Restart-Computer не указывается параметр –Wait, задачи не создается и после перезагрузки не выполняется никаких действий.

Теперь давайте рассмотрим ситуацию, когда система сама перезапускает рабочий процесс.

Автоматический перезапуск рабочего процесса

В документации по рабочим процессам сказано, что для их автоматического перезапуска могут использоваться задания Windows PowerShell (Scheduled Jobs). Однако мои попытки реализовать это на практике не увенчались успехом. Поэтому я решил использовать назначенные задания (Scheduled Tasks). В Windows PowerShell 3.0 появилось несколько командлетов для работы с назначенными заданиями. Они используют WMI и предназначены для работы только на Windows Server 2012 и Windows 8. В принципе, можно автоматизировать работу с назначенными заданиями и на других операционных системах с использованием COM, но это задача, выходящая за рамки статьи.

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

workflow test-restart {

Get-WmiObject -Class Win32_ComputerSystem | Out-File -FilePath C:\Reports\comp.txt

Get-ChildItem -Path C:\Reports | Out-File -FilePath C:\dir.txt

Restart-Computer -Wait

Get-WmiObject -Class Win32_OperatingSystem | Out-File -FilePath C:\Reports\os.txt

}

Рабочий процесс использует Get-WmiObject для получения класса Win32_ComputerSystem и помещает полученные данные в файл. Get-ChildItem получает список файлов каталога C:\Report. Таким образом мы сможем удостовериться, что первая часть рабочего процесса выполнена.

Далее используется активность Restart-Computer с параметром –Wait и компьютер перезагружается.

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

Теперь нам нужно создать назначенное задание.

$actionscript = ‘-NonInteractive -WindowStyle Normal -NoLogo -NoProfile -NoExit -Command «&»c:\reports\test-resume.ps1»»‘

$pstart = «C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe»

Get-ScheduledTask -TaskName Test | Unregister-ScheduledTask -Confirm:$false

$act = New-ScheduledTaskAction -Execute $pstart -Argument $actionscript

$trig = New-ScheduledTaskTrigger -AtLogOn

Register-ScheduledTask -TaskName Test -Action $act -Trigger $trig -RunLevel Highest

Нам нужно, чтобы назначенное задание запускало Windows PowerShell, поэтому я указал параметры запуска PowerShell в переменной $actionscript. Переменная $pstart содержит команду для запуска Windows PowerShell.

Следующая строка удаляет предыдущий экземпляр задания.

Действие задания задается при помощи командлета New-ScheduledTaskAction. Триггер определяет, когда должно запуститься задание. Я установил запуск задания на событие входа в систему, поскольку я хочу видеть его выполнение. Если хотите, вы можете заменить параметр –AtLogon на –AtStartUp.

Зарегистрируем новое назначенное задание. Убедитесь, что указан –RunLevel Highest, чтобы задание запускалось с повышенными привилегиями.

Еще одна недостающая часть мозаики – это скрипт, запускаемый назначенным заданием.

Get-ChildItem -Path C:\Reports | Out-File -FilePath C:\Reports\dir.txt

Import-Module PSWorkflow

Get-Job | Resume-Job

Здесь создается еще один список содержимого папки C:\Reports. Также в скрипте происходит импорт модуля PSWorkflow и возобновление приостановленной задачи. Если в вашей системе присутствует несколько приостановленных задач, вы можете выбрать нужную задачу по имени.

После перезагрузки компьютера и входа в систему вы увидите открытие окна Windows PowerShell и возобновление выполнения задачи.

Здесь есть некоторая странность, заключающаяся в том, что время создания файла os.txt соответствует времени создания comp.txt, хотя создание файла os.txt должно происходить уже после перезагрузки компьютера.

После завершения рабочего процесса вы можете удалить задачу обычным способом. Также вам потребуется удалить назначенное задание.

Get-ScheduledTask -TaskName Test | Unregister-ScheduledTask -Confirm:$false

Трудно назвать это элегантным решением, однако оно работает. Я продолжу пробовать использовать для этой цели задания (scheduled jobs) и в случае, если у меня что-нибудь получится, напишу об этом в своем блоге.

Gotchas

Одна из вещей, с которыми я столкнулся при тестировании, это то, что не следует запускать рабочие процессы из ISE. В соответствии с документацией, вы можете запустить рабочий процесс, подобный следующему:

workflow test-restart {

Get-WmiObject -Class Win32_ComputerSystem

Restart-Computer -Wait

Get-WmiObject -Class Win32_OperatingSystem

}

Однако, если вы запустите его из ISE, вы не обнаружите приостановленного задания – оно будет выполненным. При запуске же его из консоли, все работает как ожидается. Хочу выразить благодарность Steven Murawski за помощь при обнаружении данной особенности.

Еще одна вещь, о которой стоит помнить – сохраняйте информацию на диск, так как при перезагрузке она потеряется.

Conclusion

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

~Richard.

Автор:

Ed Wilson, Microsoft Scripting Guy

Оригинал:

http://blogs.technet.com/b/heyscriptingguy/archive/2013/01/23/powershell-workflows-restarting-the-computer.aspx


Страницы в социальных сетях:

Twitter: https://twitter.com/vsseth
Facebook: https://fb.com/inpowershell
VKontakte: https://vk.com/inpowershell


Реклама

Written by Сергей Васин

Март 14, 2013 в 11:36

Опубликовано в HeyScriptingGuyBlog, PowerShell

Tagged with ,

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s