2013-03-01 338 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" 
} 
相关问题