2013-03-01 20 views
19

Sto cercando un modo per continuare uno script PowerShell da cui è stato interrotto dopo aver chiamato un riavvio nello script. Ad esempio, sto creando un DC tramite l'automazione di Powershell e dopo aver rinominato il PC su TESTDC01, è necessario riavviare, ma dopo il riavvio, continuare con lo script per passare a dcpromo ecc.Powershell - Riavvia e continua script

È possibile?

Cheers!

+5

In passato il modo in cui ho fatto questo negli script è quello di impostare una chiave RunOnce nel Registro di sistema che esegue lo script con un parametro che dovrebbe fare la parte dopo il riavvio dello script. – EBGreen

+0

Come specificare da quale parte dello script continuare? – PnP

+0

In ritardo verso la parte, ma un modo è eseguito 'script1.ps1' che prima di riavviare il server aggiunge un programma RunOnce per eseguire' script2.ps1' ma mi piacerebbe aggiungere un po 'di sonno per consentire al server di avviarsi completamente prima di tentare di eseguire una sceneggiatura. – user4317867

risposta

18

C'è un grande articolo su TechNet della serie Hey, Scripting Guy che si riferisce a una situazione molto simile a quella che stai descrivendo: Rinominare un computer e riprendere lo script dopo il riavvio. La magia è quello di utilizzare i nuovi flussi di lavoro che fanno parte della versione 3:

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

Una volta che il flusso di lavoro è stato dichiarato (non si assegna a una variabile), si può chiamare come se si trattasse di un normale cmdlet. La vera magia è il parametro -Wait nel cmdlet Riavvia-Computer.

Rename-And-Reboot PowerShellWorkflows 

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

Se PowerShell v3 o poi non è una scelta a disposizione, si potrebbe rompere il vostro script esistente in più script più piccoli e avere uno script principale che viene eseguito all'avvio, controlla qualche stato salvato da qualche parte (file, registro, ecc.), quindi avvia l'esecuzione di un nuovo script per continuare laddove appropriato. Qualcosa di simile:

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

Basta essere sicuri di ricordare di impostare il tuo stato in modo appropriato come ci si sposta attraverso i vostri script più piccoli.

+2

Quando provo ad usare "Restart-Computer -Wait", ottengo un'eccezione: "Non posso aspettare il riavvio del computer locale.Il computer locale viene ignorato quando viene specificato il parametro Wait. " – BrainSlugs83

+0

Il vero trucco per il restartability degli articoli, specialmente se usato per l'esecuzione locale ... è che lo script crea un'attività pianificata per riprendere ... puoi fare lo stesso cosa con i propri script, flusso di lavoro o meno. –

5

Verifica PS 3.0 con flussi di lavoro. Non ho ancora lavorato con loro ma si suppone che riprendano da riavvii.

10

La risposta sopra è vera, ma si applica solo all'esecuzione remota di script PowerShell. Secondo il windows web portal, il modo per avere la vostra esecuzione localmente curriculum script da dove si era interrotta dopo che la macchina locale riavviata è in questo modo:

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 

Nota che la bandiera [System.Management.Automation.Remoting.PSSessionConfigurationData]::IsServerManager deve essere impostata su true solo se il flusso di lavoro le azioni sono pensate per essere eseguite localmente dopo il riavvio.

+1

Per cosa sono utilizzate le credenziali? Ho testato il tuo script e posso vedere il lavoro creato ma è in stato sospeso dopo il riavvio: Get-Job | Format-Table - Dimensione dell'auto – codea

0

Se questo aiuta qualcuno, quello che faccio è riavviare il server, quindi eseguire il loop fino a quando \\server\c$ non è in linea. Quindi eseguo il loop While (-not(Test-path "\\$server\c$")) per confermare che il server è di nuovo online e semplicemente continua il mio script.

Questo codice funziona ma potrebbe essere sicuramente migliorato. Genera un registro CSV dei server che vengono riavviati. Dovrebbe funzionare anche in PowerShell v2 e successivi.

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" 
} 
Problemi correlati