2 votes

Powershell, attendre la fin du premier processus.

Le script de Powershell doit se terminer si l'un des processus principaux s'est arrêté.

Ce script est le processus principal de Docker. Le conteneur Docker doit s'arrêter si l'une de ces Apps ( app1 , app2 )arrêté.

L'approche actuelle consiste à utiliser les événements de sortie pour l'une des applications et le processus d'attente pour l'autre. Existe-t-il une meilleure approche ?

$pApp1 = Start-Process -PassThru app1
$pApp2 = Start-Process -PassThru app2

Register-ObjectEvent -InputObject $pApp1 -EventName exited -Action {
    Get-EventSubscriber | Unregister-Event
    exit 1
}

Wait-Process -Id $pApp2.id
exit 1

2voto

Mathias R. Jessen Points 1039

Attendez le HasExited sur l'un ou l'autre pour changer :

$apps = 'app1','app2' |ForEach-Object { Start-Process $_ -PassThru }

while(@($apps |Where HasExited -eq $true).Count -lt 1){
  Write-Host "Waiting for one of them to exit..."
  Start-Sleep -Seconds 1
}

1voto

mklement0 Points 12597

A partir de PowerShell 7.2.1, Wait-Process lorsqu'il est donné multiple attend invariablement tous d'entre eux de se terminer avant de revenir, ce qui peut introduire un problème de sécurité. -Any de manière à n'attendre que n'importe lequel parmi eux, le sujet de Proposition GitHub #16972 ce qui simplifierait la solution à Wait-Process -Any -Id $pApp1.id, $pApp2.id


Délégation de l'attente de la sortie des processus à filetage / arrière-plan emplois évite d'avoir recours à une solution basée sur des événements ou des sondages périodiques.

# Start all processes asynchronously and get process-information 
# objects for them.
$allPs = 'app1', 'app2' | ForEach-Object { Start-Process -PassThru $_ }

# Start a thread job for each process that waits for that process to exit
# and then pass the process-info object for the terminated process through.
# Exit the overall pipeline once the first output object from one of the
# jobs is received.
$terminatedPs = $allPs | 
  ForEach-Object { Start-ThreadJob { $ps = $using:_; Wait-Process -Id $ps.Id; $ps } } |
    Receive-Job -Wait |
      Select-Object -First 1

Write-Verbose -Verbose "Process with ID $($terminatedPs.Id) exited."
exit 1

Note :

  • J'utilise le Start-ThreadJob qui offre une solution légère et beaucoup plus rapide. filetage -alternative aux tâches d'arrière-plan régulières basées sur les processus enfants, créées avec la commande Start-Job . Il est livré avec PowerShell (Core) 7+ et en Windows PowerShell peut être installé à la demande avec, par exemple, Install-Module ThreadJob -Scope CurrentUser . Dans la plupart des cas, les threads sont le meilleur choix, à la fois pour les performances et pour la fidélité au type - voir la section inférieure de la page cette réponse pourquoi.

  • Si Start-ThreadJob n'est pas disponible pour vous / ne peut pas être installé, il suffit de le substituer Start-Job dans le code ci-dessus.


PowerShell (Core) 7+ -seule solution avec ForEeach-Object -Parallel :

PowerShell 7.0 a introduit la fonction -Parallel au paramètre ForEach-Object qui, en substance, apporte le parallélisme basé sur les threads à l'interface de l'ordinateur. pipeline Il s'agit d'un moyen de créer plusieurs tâches threads implicites, une pour chaque objet d'entrée du pipeline, qui émettent leur sortie directement vers le pipeline (bien que dans un ordre non garanti).

Par conséquent, la solution simplifiée suivante est possible :

# Start all processes asynchronously and get process-information 
# objects for them.
$allPs = 'app1', 'app2' | ForEach-Object { Start-Process -PassThru $_ }

$terminatedPs = $allPs | 
  ForEach-Object -Parallel { $_ | Wait-Process; $_  } |
    Select-Object -First 1

Write-Verbose -Verbose "Process with ID $($terminatedPs.Id) exited."
exit 1

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X