Можно ли с помощью Планировщика Windows запускать задачу в воскресенье после второй и третьей субботы каждого месяца?
Длинная версия
У нас есть несколько сценариев обслуживания, которые переводят наши системы в автономный режим для исправления в 18:00 в субботу и обратно в 6:00 в воскресенье; с обслуживанием (например, обновлениями Windows), происходящим между этими периодами. Системы обычно требуются в первые и последние выходные каждого месяца, поэтому мы проводим техническое обслуживание только во 2-е и 3-е выходные каждого месяца.
Потенциальная проблема заключается в том, что если месяц начинается в воскресенье, в 3-ю субботу мы отключаем системы, но скрипт, чтобы вернуть их в онлайн-режим в воскресенье, запускался бы за неделю до этого (то есть в 3-е воскресенье месяца).
Это легко разрешить в сценарии; просто запланируйте запуск задачи каждую неделю, а затем проверьте, будет ли это воскресенье после 2-й или 3-й субботы, чтобы определить, продолжать ли выполнение или прекратить.
Тем не мение; Есть ли способ лучше?
В 2016 году затронут только один месяц (май). Почему бы просто не исключить май из расписания задач и не запускать скрипты вручную или не создать отдельную запланированную задачу на май? Вы можете легко расширить это на будущие годы, создав две запланированные задачи. Один работает по заранее заданному расписанию, но исключает те месяцы, которые начинаются в воскресенье, а второй включает только те месяцы, которые начинаются в воскресенье.
В 2016 году будет один пострадавший месяц. Два в каждом из следующих 4 лет и один в 2021 году.
NB: Я закончил тем, что просто добавил сценарий в начало своего кода, чтобы определить, находимся мы в окне или нет, а затем заставил планировщик запускать код каждую неделю.
param (
[string]$ScriptPath
,[int]$StartDay = 10
,[int]$EndDay = 24
)
#
# Only run the given script if the current date falls on a weekend between the start and end dates (is designed specifically to cope
# with tasks initiated over weekends, so requires that both the saturday and sunday of the current date fall in this window)
#
function Test-DateIsInMaintenanceWindow {
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline = $true)]
[System.DateTime]$Date = (Get-Date)
, [int]$StartDay = 10
, [int]$EndDay = 24
)
begin {
if($StartDay -ge $EndDay) {
throw "We expect the start date to be before the end date; logic for these dates being the same, or switched (i.e. to cover crossing a month boundary) are beyond the designed requirements"
}
$EndDayLocal = $EndDay - 1 #we only test the Sat / we want to ensure we account for the following Sun
}
process {
[boolean]$IsWeekend = $true #assume it's the weekend; we confirm this later
[DateTime]$Sat = $Date
switch ($Date.DayOfWeek) { #we could use 6 and 0 instead of Sat and Sun to avoid language issues; but all our servers are US/UK, and the readability is clearer with week names
'Saturday' {$Sat = $Date}
'Sunday' {$Sat = $Date.AddDays(-1)}
Default {$IsWeekend = $false}
}
write-output (new-object PSObject -prop @{
Date = $Date
Day = $Date.DayOfWeek
OK = $IsWeekend -and (($Sat.Day -ge $StartDay) -and ($Sat.Day -le $EndDayLocal))
})
}
}
if ((Test-DateIsInMaintenanceWindow).OK) {
&$ScriptPath
} else {
throw 'Script should''t run today'
}
#Code to say which weekends fall in our maintenance window
1..4000 | %{(get-date).AddDays($_)} | ?{$_.DayOfWeek -like 'S*'} | Test-DateIsInMaintenanceWindow -StartDay 10 -EndDay 24 | ft -AutoSize