简体   繁体   English

Powershell - 重启并继续脚本

[英]Powershell - Reboot and Continue Script

I'm looking for a way to continue a Powershell script from where it left off after calling a reboot in the script.我正在寻找一种方法来在脚本中调用重启后从它停止的地方继续一个 Powershell 脚本。 For example, I am building a DC via Powershell automation, and after renaming the PC to TESTDC01, need to reboot, but after the reboot, continue with the script to go on to dcpromo etc.例如,我正在通过 Powershell 自动化构建 DC,在将 PC 重命名为 TESTDC01 后,需要重新启动,但在重新启动后,继续执行脚本以继续执行 dcpromo 等。

Is this possible?这可能吗?

Cheers!干杯!

There is a great article on TechNet from the Hey, Scripting Guy series that goes over a situation very similar to what you are describing: Renaming a computer and resuming the script after reboot. TechNet 上有一篇很棒的文章,来自 Hey, Scripting Guy 系列,其中讨论了与您所描述的情况非常相似的情况:重命名计算机并在重新启动后恢复脚本。 The magic is to use the new workflows that are part of version 3:神奇的是使用作为版本 3 一部分的新工作流程:

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

Once the workflow has been declared (you don't assign it to a variable), you can call it as though it were a regular cmdlet.一旦声明了工作流(您不将其分配给变量),您就可以像调用常规 cmdlet 一样调用它。 The real magic is the -Wait parameter on the Restart-Computer cmdlet.真正的魔法是 Restart-Computer cmdlet 上的-Wait参数。

Rename-And-Reboot PowerShellWorkflows

Source: https://devblogs.microsoft.com/scripting/powershell-workflows-restarting-the-computer/来源: https : //devblogs.microsoft.com/scripting/powershell-workflows-restarting-the-computer/

If PowerShell v3 or later isn't an available choice, you could break your existing script into multiple smaller scripts and have a master script that runs at startup, checks some saved state somewhere (file, registry, etc.), then starts executing a new script to continue on where appropriate.如果 PowerShell v3 或更高版本不是可用的选择,您可以将现有脚本分解为多个较小的脚本,并拥有一个在启动时运行的主脚本,检查某处保存的状态(文件、注册表等),然后开始执行新脚本以在适当的情况下继续。 Something like:就像是:

$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" }
}

Just be sure to remember to set your state appropriately as you move through your smaller scripts.当您在较小的脚本中移动时,请务必记住适当地设置您的状态。

The above answer is true, but it will only apply to remote execution of powershell scripts.上面的答案是正确的,但它仅适用于远程执行 powershell 脚本。 According to the windows web portal , the way to have your locally running script resume from where it left off after the local machine restarted is like so:根据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

Note that the [System.Management.Automation.Remoting.PSSessionConfigurationData]::IsServerManager flag should be set to true only if the workflow actions are meant to execute locally after the restart.请注意, [System.Management.Automation.Remoting.PSSessionConfigurationData]::IsServerManager标志仅当工作流操作打算在重新启动后在本地执行时才应设置为 true。

Check out PS 3.0 with Workflows.使用工作流查看 PS 3.0。 I haven't worked with them yet but they are suppose to recover from restarts.我还没有与他们合作过,但他们应该会从重启中恢复过来。

If this helps anyone, what I do is reboot the server then loop until \\\\server\\c$ goes offline.如果这对任何人有帮助,我所做的就是重新启动服务器,然后循环直到\\\\server\\c$脱机。 Next I loop While (-not(Test-path "\\\\$server\\c$")) to confirm the server is again back online and simply continue my script.接下来我循环While (-not(Test-path "\\\\$server\\c$"))以确认服务器再次在线并继续我的脚本。

This code is working but could definitely be improved.此代码正在运行,但肯定可以改进。 It generates a CSV log of the servers being rebooted.它会生成正在重新启动的服务器的 CSV 日志。 It should also work in PowerShell v2 and newer.它也应该适用于 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"
}

Do it remotely:远程操作:

Rename-Computer -ComputerName $computer -NewName "TESTDC01" -DomainCredential $domain\$username -Force -Restart

And continue your script from that 8)然后继续你的脚本 8)

Needed to reboot my local computer and continue script after.需要重新启动我的本地计算机并在之后继续脚本。 Tried solution from @adaml but I just couldn't get the scheduled job (that ran after the reboot) to find the suspended workflow-job that should be resumed.尝试了@adaml 的解决方案,但我无法获得计划的作业(在重新启动后运行)以找到应恢复的暂停的工作流作业。 Hence, it remained suspended.因此,它一直处于暂停状态。

Get-Job didn't return the job no matter credentials or elevated.无论凭据还是提升,Get-Job 都没有返回工作。 Another strange thing was that if I ran the workflow by marking code in Powershell ISE and ran the section with F8, the job never got suspended... Had to run the whole script with F5 or called it from somewhere else.另一个奇怪的事情是,如果我通过在 Powershell ISE 中标记代码来运行工作流并使用 F8 运行该部分,则该作业永远不会被暂停......不得不使用 F5 运行整个脚本或从其他地方调用它。

To get the resume of the job working, I had to register a scheduled-Task instead of a scheduled-Job:为了使工作的简历正常工作,我必须注册一个预定任务而不是预定工作:

workflow test-restart {
    Write-Output "Before reboot" | Out-File  C:/Log/t.txt -Append

    Restart-Computer -Wait

    Write-Output "$Now2 After reboot" | Out-File  C:/Log/t.txt -Append
}

$PSPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
$Args = '-NonInteractive -WindowStyle Hidden -NoLogo -NoProfile -NoExit -Command "& {Import-Module PSWorkflow ; Get-Job | Resume-Job}"'
$Action = New-ScheduledTaskAction -Execute $PSPath -Argument $Args
$Option = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -WakeToRun
$Trigger = New-JobTrigger -AtStartUp -RandomDelay (New-TimeSpan -Minutes 5)
Register-ScheduledTask -TaskName ResumeJob -Action $Action -Trigger $Trigger -Settings $Option -RunLevel Highest


test-restart -AsJob

Thinking out loud, for benefit of people doing this in AWS/Your Cloud Provider...大声思考,为了在 AWS/您的云提供商中这样做的人的利益......

I've got the same issue with AWS instances, that will need renaming to the client standard server name, +domain join, +cert install, +Tentacle install.我在 AWS 实例上遇到了同样的问题,需要重命名为客户端标准服务器名称、+domain join、+cert install、+Tentacle install。 I am going to have the server startup script put into the user_data field of the instance via Terraform.我将通过 Terraform 将服务器启动脚本放入实例的 user_data 字段中。

I'll set EC2 instance "Renamed" tags in PS on the instance, after each part of the setup, so when the server restarts after rename, the script will look for IF "Renamed = Done" tag value, and skip this part next time the instance boots.我将在实例上的 PS 中设置 EC2 实例“重命名”标签,在设置的每个部分之后,因此当重命名后服务器重新启动时,脚本将查找 IF“重命名 = 完成”标签值,然后跳过这部分实例启动的时间。 Same logic for DomainJoined, TentacleInstalled tags etc. DomainJoined、TentacleInstalled 标签等的逻辑相同。

Code to read the tags is like:读取标签的代码如下:

$instanceId = (Invoke-RestMethod -Method Get -Uri http://169.254.169.254/latest/meta-data/instance-id)
$instance   = ((Get-EC2Instance -region $region -Instance $instanceId).RunningInstance)
$myInstance = $instance | Where-Object { $_.InstanceId -eq $instanceId }
$Renamed    = ($myInstance.Tags | Where-Object { $_.Key -eq "Renamed" }).Value

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM