PowerShell 練習 - 用 PowerShell 設定 Windows 排程跑 PowerShell
2 |
計劃把原本的手工部署與設定操作逐步轉成 PowerShell Script。這樣做有幾個好處:
- 作業標準化,避免人為失誤
寫成腳本,不管誰來操作結果都一致,不會無人交接手藝失傳,也排除腦殘眼拙手滑出錯的風險, - 大量部署或需重複執行時可節省可觀時間
例如要部署上百台機器的場合。 - 可設定排程自動化部署
例如半夜才能執行的部署作業,只需少量人員留守負責驗證結果即可。
今天我要練習的題目是「使用 PowerShell 設定 Windows 排程跑 PowerShell Script」,以下是試寫的範例:
Param ([string]$ForceOverwrite = 'N')
$taskName = "Log 定期打包壓縮"
$taskPath = "維運作業"
$ErrorActionPreference = "STOP"
$chkExist = Get-ScheduledTask | Where-Object { $_.TaskName -eq $taskName -and $_.TaskPath -eq "\$taskPath\" }
if ($chkExist) {
if ($ForceOverwrite -eq 'Y' -or $(Read-Host "[$taskName] 已存在,是否刪除? (Y/N)").ToUpper() -eq 'Y') {
Unregister-ScheduledTask $taskName -Confirm:$false
}
else {
Write-Host "放棄新增作業" -ForegroundColor Red
Exit
}
}
$action = New-ScheduledTaskAction -Execute "Powershell.exe" -Argument '-NoProfile -ExecutionPolicy ByPass -NonInteractive -WindowStyle Hidden -Command "D:\Workroom\PSLab\ArchiveLogs.ps1 D:\Logs\W3SVC1" '
$trigger = New-ScheduledTaskTrigger -Weekly -WeeksInterval 4 -DaysOfWeek Sunday -At 1am
Register-ScheduledTask $taskName -TaskPath $taskPath -Action $action -Trigger $trigger -User "SYSTEM"
整理幾個重點:
- PowerShell 有一系列內建的排程管理 Cmdlet,例如:Register-ScheduledTask、Start-ScheduledTask,官方文件寫得十分詳細還有大量範例,是最權威的參考來源。
- 設定排程的基本流程為:用 New-ScheduledTaskAction 指定動作、用 New-ScheduledTaskTrigger 設定執行週期,再用 Register-ScheduledTask 輸入名稱、路徑跟執行身分,參數幾乎都能對映到操作介面的欄位,加上文件完整,不難上手。
- 最前方我加了一小段檢查,若發現排程已存在會提示刪除重新設定。
- Windows 排程提供類似資料夾的概念,可將排程分群方便檢查管理,在註冊排程工作時指定 TaskPath 即可。
- 範例將排程設成用 Local System 身分執行不需提供密碼,若要使用一般帳號並互動輸入密碼,可參考淺談 PowerShell 中的密碼字串加密處理 介紹過的技巧。
- 在排程執行 PowerShell,主程式為 powershell.exe,參數可寫成
-NoProfile -ExecutionPolicy ByPass -NonInteractive -WindowStyle Hidden -Command "ps1路徑 ps1參數1 ps1參數2"
,其中 -NoProfile 代表不載入任何 Profile 避免干擾,-NonInteractive 可在遇到等待使用者輸入時直接報錯避免卡住,WindowStyle Hidden 會隱藏視窗,ExecutionPolicy ByPass 確保 .ps1 被允許執行。Command 為 .ps1 路徑跟 .ps1 需要的參數,若 .ps1 沒有輸入參數,則可寫成-File .ps1路徑
。以上設定 .ps1 會默默執行默默結束,若要手動測試檢視其輸出或錯誤訊息,則可拿掉 -WindowStyle Hidden,加上 -NoExit。參考
執行結果像這樣:
不過我發現一個問題 - PowerShell 提供的排程管理指令不知何故無法設成每月固定一天執行,New-ScheduledTaskTrigger 有 Once、Daily、Weekly 選項,但沒有 Monthly。研究了一下,好像只能改用 schtasks.exe,例如:參考
#New-ScheduledTaskTrigger 不支援 Monthly,改用 schtasks
# 用 PowerShell 陣列轉字串做出以空白間隔的參數字串,含空白的參數值要加雙引號
$taskParams = @(
"/Create",
"/TN", "`"$taskPath\$taskName`"",
"/SC", "monthly",
"/D", "1", #每個月幾號
"/ST", "01:00", #開始時間
"/TR", "`"powershell.exe -NoProfile -ExecutionPolicy ByPass -NonInteractive -WindowStyle Hidden -Command 'C:\Workroom\PSLab\ArchiveLogs.ps1 D:\Logs\W3SVC1'`"",
"/RU", "System"
)
schtasks.exe $taskParams
練習完畢。
Exmaple of how to set a scheduled PowerShell script with PowerShell.
Comments
# by Chui-Wen Chiu
應該是 -NonInteractive
# by Jeffrey
to Chui-Wen Chiu,感謝,已更正。