Ejecutar comandos en paralelo en PowerShell

  1. el subprocesamiento múltiple de Windows PowerShell
  2. Ejecución Paralela de Scripts con PSJobs
  3. Mantenga un registro de nuestros trabajos
  4. Recuperar salida de trabajo
  5. Crear trabajos programados
Ejecutar comandos en paralelo en PowerShell

La sesión predeterminada de PowerShell es de subproceso único. Ejecuta un comando y pasa al siguiente comando.

Este método es excelente ya que mantiene todo repetible y no usa muchos recursos. En ese caso, es hora de empezar a pensar en subprocesos múltiples.

Este artículo nos enseñará a comprender y usar varias técnicas de subprocesos múltiples de PowerShell para procesar múltiples flujos de datos simultáneamente pero administrados a través de la misma consola.

el subprocesamiento múltiple de Windows PowerShell

Multithreading es un método para ejecutar más de un comando a la vez. PowerShell generalmente usa un solo hilo; hay muchas formas de usar más de una para paralelizar nuestro script.

El propósito principal de los subprocesos múltiples es disminuir el tiempo de ejecución del código. Esta disminución de tiempo es a cambio de un mayor requisito de potencia de procesamiento.

Además, muchas acciones se realizan a la vez cuando se realizan subprocesos múltiples, lo que requiere más recursos del sistema.

Tenga en cuenta que no veremos una escala perfecta. Girar y derribar elementos en el guión llevará algún tiempo.

PowerShell necesita ejecutar el código usando un solo subproceso y listo. Usaremos el subproceso original utilizado para ejecutar nuestra consola para administrar los otros subprocesos con múltiples subprocesos.

Ese hilo original se maximizará en un punto determinado, manteniendo todos los demás hilos en línea.

Ejecución Paralela de Scripts con PSJobs

Una de las formas más convenientes de realizar varios subprocesos en un script es con PSJobs. PSJobs tiene cmdlets integrados en el módulo Microsoft.PowerShell.Core.

El módulo Microsoft.PowerShell.Core se ha incluido en todas las versiones de PowerShell desde la versión 3. Los comandos de este módulo nos permiten ejecutar código en segundo plano mientras continuamos ejecutando código diferente en primer plano.

Get-Command *-Job

Mantenga un registro de nuestros trabajos

A continuación encontraremos una lista de los estados más comunes que puede tener un trabajo.

  1. Completado: el trabajo ha finalizado y podemos recuperar los datos de salida o eliminar el trabajo.
  2. En ejecución: el trabajo se está ejecutando y no se puede eliminar sin detener el trabajo a la fuerza. No se puede recuperar la salida.
  3. Bloqueado: el trabajo aún se está ejecutando, pero se le solicita al usuario información adicional antes de que pueda continuar con la ejecución.
  4. Error: se produjo un error de finalización mientras se ejecutaba el trabajo.

Usamos el comando Get-Job para iniciar el estado del trabajo y todos los atributos de nuestros trabajos. La salida de un trabajo donde podemos ver el estado es En ejecución.

El siguiente ejemplo ejecuta el código Start-Sleep 5 dentro de una cita usando el comando Start-Job. Luego, se devuelve el estado de ese trabajo mediante el comando Get-Job.

Código de ejemplo:

Start-Job -Scriptblock {Start-Sleep 5}
Get-Job

Producción :

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
1      Job1            BackgroundJob   Running       True            localhost            Start-Sleep 5

Recuperar salida de trabajo

A veces, el código dentro del trabajo devuelve la salida. Podemos recuperar ese código usando el comando Receive-Job.

Acepta PSJob como entrada y luego escribe el trabajo del trabajo en la consola. Se ha almacenado todo lo que resultó del trabajo mientras se ejecutaba.

Cuando se recupera el trabajo, muestra todo lo que estaba almacenado.

Un ejemplo de esto sería ejecutar el siguiente script. Este script creará e iniciará un trabajo para escribir la cadena Hello World en la salida.

Luego obtiene el resultado del trabajo y lo muestra en la consola.

Código de ejemplo:

$Job = Start-Job -ScriptBlock {Write-Output 'Hello World'}
Receive-Job $Job

Producción :

Hello World

Crear trabajos programados

Otra forma de interactuar con PSJobs es a través de un trabajo programado. Es similar a una tarea programada de Windows que podemos configurar con el Programador de tareas.

Las citas programadas crean una forma de programar fácilmente bloques de secuencias de comandos de PowerShell complejos en una tarea programada. Luego, podemos ejecutar un PSJob en segundo plano basado en disparadores.

Activadores de trabajo

Los desencadenantes de trabajos pueden ser un momento específico cuando un usuario inicia sesión, cuando se inicia el sistema y muchos otros. También podemos hacer que los disparadores se repitan a intervalos.

Dichos disparadores se definen con el comando New-JobTrigger, que especifica un disparador que ejecutará el trabajo programado.

Además de tener un disparador de PSJob, aún tendríamos un bloque de script como el que se usa con un PSJob regular. Una vez que tengamos tanto el disparador como el bloque de script, usaríamos el comando Register-ScheduledJob para crear el trabajo, como se muestra en la siguiente sección.

Este comando especifica los atributos del trabajo programado, como el bloque de script que se ejecutará y los disparadores creados con el comando New-JobTrigger.

Tal vez necesitemos algún código de PowerShell para ejecutar cada vez que alguien inicie sesión en una computadora. Podemos crear un trabajo programado para esto.

Primero definiríamos un disparador usando New-JobTrigger y especificaríamos el trabajo programado como se indica a continuación. Este trabajo programado a continuación escribirá una línea en un archivo de registro cada vez que alguien inicie sesión en el sistema.

Código de ejemplo:

$Trigger = New-JobTrigger -AtLogon
$Script = {"User $env:USERNAME logged at $(Get-Date -Format 'y-M-d H:mm:ss')" | Out-File -FilePath C:\Temp\User_Login.log -Append}

Register-ScheduledJob -Name Login_Log -ScriptBlock $Script -Trigger $Trigger

Producción :

Id         Name            JobTriggers     Command                                  Enabled   
--         ----            -----------     -------                                  -------   
1          Login_Log       1               "User $env:USERNAME logged at $(Ge... True

Una vez que ejecutemos los comandos anteriores, obtendremos un resultado similar a cuando hacemos un nuevo trabajo que mostrará la ID, el bloque de script y algunos otros atributos.

Utilice el parámetro AsJob

Otro uso de los trabajos es el parámetro -AsJob integrado en muchos comandos de PowerShell. Como hay muchos comandos diferentes, podemos encontrarlos todos usando Get-Command.

Get-Command -ParameterName AsJob

Uno de los cmdlets más frecuentes es Invoke-Command. Por lo general, cuando ejecutamos este comando, comenzará a ejecutar un comando de inmediato.

Sin embargo, mientras que algunos comandos regresarán inmediatamente, permitiéndonos continuar con lo que estábamos haciendo, algunos esperarán hasta que finalice el cmdlet.

Si bien podemos usar el parámetro AsJob con la máquina local la mayor parte del tiempo, el cmdlet Invoke-Command no tiene una opción nativa para ejecutarse en la máquina local. Sin embargo, existe una solución al usar Localhost como el valor del parámetro ComputerName.

Ejemplo:

Invoke-Command -ScriptBlock {Start-Sleep 5} -ComputerName localhost

El siguiente script usa el cmdlet Invoke-Command para dormir durante cinco segundos y luego repite el mismo comando usando el parámetro AsJob para mostrar la diferencia en los tiempos de ejecución.

Código de ejemplo:

Measure-Command {Invoke-Command -ScriptBlock {Start-Sleep 5}}
Measure-Command {Invoke-Command -ScriptBlock {Start-Sleep 5} -AsJob -ComputerName localhost}

Producción :

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 5
Milliseconds      : 20
Ticks             : 50206571
TotalDays         : 5.81094571759259E-05
TotalHours        : 0.00139462697222222
TotalMinutes      : 0.0836776183333333
TotalSeconds      : 5.0206571
TotalMilliseconds : 5020.6571

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 36
Ticks             : 365754
TotalDays         : 4.23326388888889E-07
TotalHours        : 1.01598333333333E-05
TotalMinutes      : 0.00060959
TotalSeconds      : 0.0365754
TotalMilliseconds : 36.5754
Marion Paul Kenneth Mendoza avatar Marion Paul Kenneth Mendoza avatar

Marion specializes in anything Microsoft-related and always tries to work and apply code in an IT infrastructure.

LinkedIn