Заметки о Windows и других программных продуктах Microsoft...

Запуск PowerShell скриптов по расписанию

Запуск PowerShell скриптов по расписанию

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

Итак, предположим, у меня есть скрипт start.ps1, который мне необходимо запускать ежедневно в течении 10 дней. Есть два способа решить эту задачу.

Способ 1

Для запуска скрипта воспользуемся оснасткой Task Scheduler, он же планировщик заданий. Найти его можно в разделе Administrative Tools, либо нажав Win+R и введя команду taskschd.msc. Открываем планировщик и в разделе Actions выбираем пункт Create Task.

создаем запланированное задание в Task Scheduler

 

На вкладке General указываем имя и описание задания, а также (по необходимости) пользователя, от имени которого задание будет запускаться. Для того, чтобы задание выполнялось вне зависимости от того, залогинен ли пользователь в системе, выбираем опцию «Run whether user is logged on or not». Если для выполнения задания требуется повышение привилегий, то отмечаем опцию «Run with highest privileges».

новое задание, вкладка General

 

Далее идем на вкладку Triggers и создаем новый триггер, в котором будет храниться расписание запуска нашего задания. В поле Start указываем дату и время запуска, а в поле Expire — дату и время завершения задания. Указываем выполнять задание ежедневно (Daily) и задаем период повтора (Recur every) 1 день.

Примечание. Если вы хотите запускать задание чаще, чем раз в день, то надо выбрать одноразовое выполнение (One time), а в разделе Advanced settings отметить пункт Repeat task every и указать время повторения, минимум 5 минут, максимум 1 час. Если этого недостаточно, то дополнительно в поле Delay task for up to можно указать временную задержку.

задаем условие для запуска задания

 

И основное. Переходим на вкладку Action и указываем действие для запланированного задания. Напомню, что в целях безопасности PowerShell скрипты могут выполняться только интерактивно, то есть сначала надо запустить оболочку PowerShell и уже в ней указать путь к скрипту. Поэтому в поле «Action» указываем запуск powershell.exe, а в поле «Add Arguments» параметр -File и путь к нашему скрипту, вот так:

-File ″C:\Scripts\start.ps1″

Также в поле аргументы можно указать:

-Command — выполняет указанные команды и любые другие параметры. Этот параметр тоже можно использовать для запуска скрипта, например: -Command ″& {C:\Scripts\start.ps1}″. Кроме того, с его помощью можно передавать в скрипт параметры: -Command ″& {C:\Scripts\start.ps1 -a 1 -b 3}″;
-ExecutionPolicy — задает политику выполнения скриптов для текущего сеанса, может принимать значения Unrestricted, RemoteSigned, AllSigned и Restricted. Заданная политика будет действовать только в текущем сеансе и имеет приоритет над любыми ранее созданными политиками;
-NonInteractive — отключить вывод интерактивных запросов к пользователю;
-WindowStyle Hidden — запуск окна PowerShell в скрытом режиме, незаметно для пользователя;
-NoProfile — предотвращает загрузку профиля, что может несколько ускорить выполнение скрипта;
-NoExit — оставить оболочку открытой после отработки скрипта. Это может понадобиться при проверке и отладке скрипта.

указываем действие для запланированного задания

 

Заполнив необходимые поля жмем ОК и сохраняем задание. Теперь скрипт будет запускаться по расписанию ежедневно в заданное время в течении 10 дней.

Способ 2

В PowerShell 3.0 появился новый функционал Sheduled Job, дающий возможность создавать запланированные задания прямо из консоли, не пользуясь оснасткой планировщика. Воспользуемся им для планового запуска нашего скрипта.

Сначала создаем расписание запуска (ежедневно в полпятого вечера, в течении 10 дней):

$t = New-JobTrigger -Daily -At 4:30PM -DaysInterval 10

Затем сохраняем в переменной учетные данные:

$cred = Get-Credential contoso\administrator

В качестве опции указываем запуск задания с повышенными привилегиями:

$o = New-ScheduledJobOption -RunElevated

И регистрируем задание с именем Start:

Register-ScheduledJob -Name Start -FilePath C:\Scripts\start.ps1 -Trigger $t -Credential $cred -ScheduledJobOption $o

создание запланированного задания в PowerShell

 

Чтобы убедится в том, что задание создано, можно открыть планировщик и найти наше задание в разделе Microsoft\Windows\PowerShell\SheduledJobs.

запланированное задание в Task Sheduler

 

Примечание.  Для каждого запланированного задания PowerShell в директории %systemdrive%\Users\%username%\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs создается одноименная папка. В этой папке находится само задание в XML-файле и папка Output, в которой, в подпапках по времени выполнения, хранится история выполнения задания — результат выполнения (файлs Result.xml) и статус задания (Status.xml). Эти файлы могут пригодиться для отладки и диагностики в том случае, если задание не отрабатывает должным образом.

Execution Policy

В заключение напомню об одном немаловажном моменте, а именно о политике выполнения скриптов Execution Policy. Посмотреть текущее значение политики можно командой Get-ExecutionPolicy. Политика выполнения может иметь значения:

• Restricted — блокируется выполнение любых скриптов. Значение по умолчанию;
• AllSigned — разрешено выполнение скриптов, имеющих цифровую подпись;
• RemoteSigned — скрипты, подготовленные на локальном компьютере, можно запускать без ограничений, скрипты, загруженные из Интернета —  только при наличии цифровой подписи;
• Unrestricted — разрешено выполнение любых скриптов. При запуске неподписанного скрипта, который был загружен из Интернета, программа может потребовать подтверждение;
• Bypass — ничего не блокируется, никакие предупреждения и запросы не появляются.

Обычно для безпроблемного выполнения скриптов достаточно задать значение RemoteSigned. Изменить текущее значение можно командой Set-ExecutionPolicy, например:

Set-ExecutionPolicy RemoteSigned -force

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

 
 
Комментарии
Алексей

Что я делаю не так! Вроде все как описано, результата не вижу… результат последнего действия (0xFFFD0000) WS2008R2 Ent, Exchange 2010

Тут можно только гадать :). Сам скрипт, без планировщика, отрабатывает нормально?

Алексей

конечно, без планировщика все ок! Политика запуска — RemoteSigned. Я сейчас по статье сделал опять все тоже самое, там тестовый простейший скрипт Send-MailMessage с параметрами, тоже без планировщика отрабатывает, а планировщик не запускает… не по расписанию не вручную =(

Чтобы выяснить, что происходит при запуске скрипта, можно добавить в начало скрипта строчку Start-Transcript -Path C:\transcript.txt, в конец Stop-Transcript. И посмотреть, что в файле.

Андрей

Почему то в такой форме не заработало. Просто Start-Transcript и Stop-Transcript…При каждом запуске пишет в отдельные файлики с полным временем запуска в Документы пользователя

Андрей

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

=) не помню копировал или набирал… мне казалось, что сам набирал… В результате убрал совсем, благо у меня в путях нет пробелов и все заработало!

Сергей

Спасибо, все работает, долго мучился тоже на кривые кавычки нарвался из строки -File ″C:\Scripts\start.ps1″, перебил, планировщик заработал, и чего сразу коменты не прочитал.
У меня вопрос, планировщик делает копии в одно и тоже место. В журнале пишет всё ОК, в проводнике вижу только первую сделанную копию, т.е дата изменения файлов соответствует первой копии. Как правильно нужно в этом случае поступать, удалять предварительно старую копию?

Про какие копии идет речь?

Сергей

экспорт виртуальной машины скрипт Export-VM -Name scg -Path G:\backup

Сергей

уточню, хост hyper-v на 2012r2

Вроде Export-VM не умеет перезаписывать данные, так что надо либо удалять предыдущую копию, либо делать экспорт в отдельные папки.

Виталий

$o = New-SheduledJobOption -RunElevated в слове шедулед опечатка, нужно $o = New-ScheduledJobOption -RunElevated между Эс и Эйч буква Си должна присутствовать)

Действительно, ошибочка вышла. Исправил.

Алексей

Добрый день!
Наступило событие [какое-то событие] выполняется скрипт [какой-то скрипт].ps1 как параметры события передать скрипту. Очень нужно. Спасибо

Например так: Происходит событие -> Событие записывается в системный лог -> Запускается скрипт -> Скрипт идет в лог и ищет нужное событие -> Событие имеет свойства, которые используются скриптом в дальнейшей работе.

Сергей

Напишу, может пригодится кому. Сейчас некоторое время потратил пока не разобрался.
Есть скрипт который бэкапит виртуалку (через Export-VM) в СЕТЕВУЮ папку. При этом если запускать скрипт интерактивно на гипервизоре, то нужно что бы в разрешениях на папку куда бэкапится была возможность записи для доменной учётки самого гипервизора (по имени компа), а НЕ ДЛЯ учётки пользователя который запускает скрипт.
Если же запускать тот же самый скрипт из шедулера, то уже почему-то нужно давать разрешение именно на учётку пользователя под которым шедулер запускает задачу. При этом само собой необходимо запоминать пароль этой учётки в задаче. А так же необходимо, что бы этот пользователь являлся админом на гипервизоре (галочки «Выполнить с наивысшими правами» не достаточно).

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

Гипервизор если что Hyper-V Server 2012 R2.

Дмитрий

Спасибо, получилось запустить простой ps1-скрипт. Хочу выполнить набор команд внутри git-shell, но не получается.
Сам git-shell запускается с ярлыка «AppData\Local\GitHub\GitHub.appref-ms —open-shell» и как в него прокинуть другой ps1-скрипт, не представляю.

Михаил

Помогите советом. При запуске скрипта на короткое время появляется черное окно и сразу исчезает. Можно ли избавиться от этого? Как это можно сделать?

Можно попробовать запуск powershell.exe с ключом -WindowStyle Hidden

AlektroNik

Ситуация следующая … есть cкрипт \\domain.local\SYSVOL\domain.local\scripts\WSUS_Clean.ps1.
Создана задача с запуском от имени пользователя «система» с выполнением с наивысшим правами.
Действие: PowerShell -Command «»

Если запуская просто из консоли cmd или PowerShell с запуском от админа, действие выполняется.
Если кладу скрипт локально на диск «C:\WSUS_Clean.ps1» и меняю команду в планировщике задач на PowerShell -Command «», то задача тоже выполняется.
НО если выполнять действие с указанием не сетевую шару PowerShell -Command «», то задача выполняется моментально и завершается удачно, но скрипт по факту не отрабатывает.

Вопрос. Почему может не отрабатывать скрипт PowerShell из планировщика задач, если в действие указан сетевой путь? Прав хватает, ExecutionPolicy вроде тоже.

Первое что бросается в глаза — как у пользователя «система», от имени которого запускается скрипт, могут быть права доступа на сетевую шару.