2013-03-01 335 views
19

我正在尋找一種方法,可以在腳本中調用重新引導後從其停止的位置繼續運行Powershell腳本。例如,我正在通過Powershell自動化構建一個DC,並且在將PC重命名爲TESTDC01之後,需要重新啓動,但在重新啓動後,繼續使用腳本繼續進行到dcpromo等。Powershell - 重新啓動並繼續腳本

這可能嗎?

乾杯!

+5

在過去,我已經在腳本中這樣做的方法是設置在運行與它應該做的腳本後重啓部分參數腳本註冊表中的RunOnce項。 – EBGreen 2013-03-01 21:05:23

+0

我將如何指定腳本的哪部分繼續? – PnP 2013-03-01 21:08:28

+0

晚了,但一種方式是運行'script1.ps1',在重新啓動服務器之前添加一個RunOnce regkey來運行'script2.ps1',但我會提醒一些睡眠以允許服務器完全啓動,然後嘗試運行一個腳本。 – user4317867 2016-02-28 21:19:04

回答

18

在嗨,Scripting Guy系列的TechNet上有一篇很棒的文章,講述了與您所描述的情況非常相似的情況:重新命名計算機並在重新啓動後恢復腳本。神奇的是使用新的工作流是3版本的一部分:

workflow Rename-And-Reboot { 
    param ([string]$Name) 
    Rename-Computer -NewName $Name -Force -Passthru 
    Restart-Computer -Wait 
    Do-MoreStuff 
} 

一旦工作流程已申報(你不把它分配給一個變量),你可以調用它,就好像它是一個正規小命令。真正的魔力是Restart-Computer cmdlet上的-Wait參數。

Rename-And-Reboot PowerShellWorkflows 

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

如果PowerShell的V3或更高版本不是一個可用的選擇,你可能會破壞你現有的腳本爲多個較小的腳本和有運行在啓動一個主腳本,檢查一些保存狀態某處(文件,註冊表等),然後開始執行新腳本以在適當的地方繼續。例如:

$state = Get-MyCoolPersistedState 
switch ($state) { 
    "Stage1" { . \Path\To\Stage1.ps1 ; break } 
    "Stage2" { . \Path\To\Stage2.ps1 ; break } 
    "Stage3" { . \Path\To\Stage3.ps1 ; break } 
    default { "Uh, something unexpected happened" } 
} 

請務必記住在您移動較小的腳本時適當地設置您的狀態。

+2

當我嘗試使用「Restart-Computer -Wait」時,出現異常:「無法等待本地計算機重新啓動。當指定Wait參數時,本地計算機將被忽略。「 – BrainSlugs83 2014-11-14 19:46:57

+0

文章重啓能力的真正竅門,特別是當用於本地執行時......是腳本創建一個計劃任務以恢復...您可以執行相同操作用你自己的腳本,工作流程或不是。 – 2017-09-07 14:24:53

5

檢查PS 3.0的工作流程。我還沒有與他們合作,但他們假設從重新啓動恢復。

10

上述答案是正確的,但它只適用於遠程執行powershell腳本。 按照windows web portal,途中有從上次停止的地方你的本地運行的腳本恢復後,在本地機器重啓就像這樣:

workflow Resume_Workflow 
{ 
    ..... 
    Rename-Computer -NewName some_name -Force -Passthru 
    Restart-Computer -Wait 
    # Do some stuff 
    ..... 
} 
# Create the scheduled job properties 
$options = New-ScheduledJobOption -RunElevated -ContinueIfGoingOnBattery -StartIfOnBattery 
$secpasswd = ConvertTo-SecureString "Aa123456!" -AsPlainText -Force 
$credential = New-Object System.Management.Automation.PSCredential ("WELCOME\Administrator", $secpasswd) 
$AtStartup = New-JobTrigger -AtStartup 

# Register the scheduled job 
Register-ScheduledJob -Name Resume_Workflow_Job -Trigger $AtStartup -ScriptBlock ({[System.Management.Automation.Remoting.PSSessionConfigurationData]::IsServerManager = $true; Import-Module PSWorkflow; Resume-Job -Name new_resume_workflow_job -Wait}) -ScheduledJobOption $options 
# Execute the workflow as a new job 
Resume_Workflow -AsJob -JobName new_resume_workflow_job 

注意,[System.Management.Automation.Remoting.PSSessionConfigurationData]::IsServerManager標誌應當設置爲true,只有在工作流程操作意味着在重新啓動後在本地執行。

+1

什麼是證書?我測試了你的腳本,我可以看到創建的作業,但它在重啓後處於掛起狀態:Get-Job | Format-Table - 自動尺寸 – codea 2016-09-09 17:34:01

0

如果這有助於任何人,我所做的是重新啓動服務器,然後循環,直到\\server\c$脫機。接下來我循環While (-not(Test-path "\\$server\c$"))以確認服務器再次恢復在線狀態,並簡單地繼續我的腳本。

此代碼正在工作,但絕對可以改進。它會生成重新啓動的服務器的CSV日誌。它也應該在PowerShell v2和更新的版本中工作。

Param([Parameter(Mandatory=$true)][string]$server) 
$ErrorActionPreference = "SilentlyContinue" 

Try{ 
$LastReboot = Get-EventLog -ComputerName $server -LogName system | Where-Object {$_.EventID -eq '6005'} | Select -ExpandProperty TimeGenerated | select -first 1 

(Invoke-WmiMethod -ComputerName $server -Path "Win32_Service.Name='HealthService'" -Name PauseService).ReturnValue | Out-Null 

Restart-Computer -ComputerName $server -Force 

#New loop with counter, exit script if server did not reboot. 
$max = 20;$i = 0 
DO{ 
IF($i -gt $max){ 
     $hash = @{ 
      "Server" = $server 
      "Status" = "FailedToReboot!" 
      "LastRebootTime" = "$LastReboot" 
      "CurrentRebootTime" = "FailedToReboot!" 
      } 
$newRow = New-Object PsObject -Property $hash 
$rnd = Get-Random -Minimum 5 -Maximum 40 
Start-Sleep -Seconds $rnd 
Export-Csv D:\RebootResults.csv -InputObject $newrow -Append -Force 
    "Failed to reboot $server" 
    exit}#exit script and log failed to reboot. 
    $i++ 
"Wait for server to reboot" 
    Start-Sleep -Seconds 15 
}#end DO 
While (Test-path "\\$server\c$") 

$max = 20;$i = 0 
DO{ 
IF($i -gt $max){ 
     $hash = @{ 
      "Server" = $server 
      "Status" = "FailedToComeOnline!" 
      "LastRebootTime" = "$LastReboot" 
      "CurrentRebootTime" = "FailedToReboot!" 
      } 
$newRow = New-Object PsObject -Property $hash 
$rnd = Get-Random -Minimum 5 -Maximum 40 
Start-Sleep -Seconds $rnd 
Export-Csv D:\RebootResults.csv -InputObject $newrow -Append -Force 
    "$server did not come online" 
    exit}#exit script and log failed to come online. 
    $i++ 
    "Wait for [$server] to come online" 
    Start-Sleep -Seconds 15 
}#end DO 
While (-not(Test-path "\\$server\c$")) 

$CurrentReboot = Get-EventLog -ComputerName $server -LogName system | Where-Object {$_.EventID -eq '6005'} | Select -ExpandProperty TimeGenerated | select -first 1 
    $hash = @{ 
      "Server" = $server 
      "Status" = "RebootSuccessful" 
      "LastRebootTime" = $LastReboot 
      "CurrentRebootTime" = "$CurrentReboot" 
       } 

$newRow = New-Object PsObject -Property $hash 
$rnd = Get-Random -Minimum 5 -Maximum 40 
Start-Sleep -Seconds $rnd 
Export-Csv D:\RebootResults.csv -InputObject $newrow -Append -Force 

}#End Try. 

Catch{ 
$errMsg = $_.Exception 
"Failed with $errMsg" 
} 
相關問題