Workflows
Introducción
Los workflows (flujos de trabajo) se introdujeron con la versión 3.0 de PowerShell. Como recordatorio, fueron Windows Server 2012 y Windows 8 los que trajeron esta versión. En aquella época, la noción de nube estaba bien asentada y la virtualización ya había conquistado prácticamente todas las empresas. Por lo tanto, era habitual gestionar varios cientos o incluso miles de servidores Windows. Entonces, ¿cómo hacerlo? El equipo de PowerShell respondió a esta pregunta con flujos de trabajo.
Los flujos de trabajo son definidos y gestionados por la Windows Workflow Foundation (WWF). Esta tecnología está presente en la plataforma .NET desde la versión 3. PowerShell interactúa con esta tecnología a través de un formato de datos llamado XAML. Este formato se utiliza en el diseño de interfaces gráficas WPF (véase el capítulo Creación de interfaces gráficas). El motor WWF simplemente interpreta los archivos XAML sin preocuparse de su procedencia. Esto significa que los workflows no son exclusivos de PowerShell y pueden ser utilizados por otras aplicaciones.
El objetivo de este capítulo es introducirte en el uso de esta tecnología, advirtiéndote al mismo tiempo de los obstáculos que puede encontrar. Se trata de una herramienta formidable, con posibilidades y casos de uso que van más...
Creación de un workflow
1. Palabra clave workflow
Para crear un workflow, es necesario conocer una palabra clave: workflow. La sintaxis asociada a esta palabra clave es casi idéntica a la de una función avanzada. La única diferencia es que la instrucción [CmdletBinding()] solo autoriza determinados atributos.
Sintaxis
workflow <Verbe-Nom> {
[CmdletBinding()]
param(
<bloque de parámetros>
)
<procesamiento del workflow ...>
}
El nombre de un workflow tiene la misma forma que el de una función: Verbo-nombre. Para más detalles, consulte el capítulo Funciones avanzadas.
Creación del primer workflow:
workflow Demo-Workflow {
Write-Output "I am a flow"
}
Se recomienda usar Write-Output en lugar de Write-Host. Esta última es una de las restricciones que se explicarán más adelante.
Al igual que las funciones, los flujos de trabajo pueden listarse mediante el comando Get-Command, especificando el valor del workflow en el parámetro -CommandType.
PS > Get-Command -CommandType workflow
CommandType Name Version Source
----------- ---- ------- ------
workflow Demo-Workflow
El workflow está presente.
2. Gestión de parámetros
Como ya se ha mencionado, los workflows permiten la configuración de parámetros. Existen varios tipos de parámetros. Hay parámetros comunes, los contenidos en el bloque param(), y parámetros específicos de los workflows.
a. Parámetros comunes
Los flujos de trabajo aceptan parámetros comunes, como -Verbose o -ErrorAction. Por lo tanto, puede...
Restricciones
No se puede hacer cualquier cosa con los workflows. Tienen limitaciones técnicas que derivan directamente de su modo de funcionamiento. Como recordatorio, se traducen en archivos XAML que describen actividades, se ejecutan como jobs y dependen del servicio WinRM. Eso implica gestionar muchos elementos para mantener un funcionamiento similar al de un script o función estándar de PowerShell.
En general, hay que tener en cuenta los siguientes aspectos al utilizar un workflow:
-
restricción de lenguaje
-
uso limitado de variables
-
serialización y deserialización de objetos
-
no es posible utilizar alias de parámetros ni pasar parámetros por posición.
1. Restricciones en los comandos
En consecuencia, algunos de los comandos básicos de PowerShell no tienen equivalente como actividad de workflow, y por lo tanto no son compatibles con XAML. He aquí una lista no exhaustiva:
Add-History |
Add-PSSnapin |
Clear-History |
Clear-Variable |
Complete-Transaction |
Connect-Wsman |
Debug-Process |
Disable-PSBreakpoint |
Disconnect-Wsman |
Enable-PSBreakpoint |
Enter-PSSession |
Exit-PSSession |
Export-Alias |
Export-Console |
Get-Alias |
Get-History |
Get-PSBreakpoint |
Get-PSCallStack |
Get-PSSnapin |
Get-Transaction |
Get-Variable |
Import-Alias |
Invoke-History |
New-Alias |
New-Variable |
Out-GridView |
Remove-PSSnapin |
Remove-Variable |
Set-Alias |
Set-PSBrealkpoint |
Set-PSDebug |
Set-StrictMode |
Set-Variable |
Start-Transaction |
Start-Transcript |
Stop-Transcript |
Trace-Command |
Undo-Transaction |
Use-Transaction |
Write-Host |
También se excluye el conjunto de comandos de formato (Format-*), así como cualquier comando que requiera la acción del usuario.
Algunos comandos solo pueden ejecutarse en el sistema local:
Add-Member |
Compare-Object |
ConvertFrom-Csv |
ConvertFrom-Json |
Convert-From-StringData |
Convert-Path |
ConvertTo-Csv |
ConvertTo-Html |
ConvertTo-Json |
ConvertTo-Xml |
Foreach-Object |
Get-Host |
Get-Member |
Get-Random |
Get-Unique |
Group-Object |
Measure-Command |
Measure-Object |
New-PSSessionOption |
New-PSTransportOption |
New-TimeSpan |
Out-Default |
Out-Host |
Out-Null |
Out-String |
Select-Object |
Sort-object |
Update-List |
Where-Object |
Write-Debug |
Write-Error |
Write-Host |
Write-OutPut |
Write-Progress |
Write-Verbose |
|
2. Restricciones sobre los objetos
La serialización y deserialización de objetos presenta el mismo problema que en una sesión remota de PowerShell. Es posible acceder a las propiedades, pero no invocar métodos...
Ejecución en paralelo
1. Bloque parallel
Los workflows permiten realizar acciones simultáneamente. Por defecto, las actividades se realizan secuencialmente. La segunda actividad espera hasta que la primera haya terminado de procesarse antes de comenzar. Para iniciarlas en paralelo, utilice la palabra clave parallel dentro del flujo de trabajo. Esta palabra clave también es específica del workflow, como InlineScript.
Sintaxis:
workflow <verb-noun> {
parallel {
#Actividad 1
#Actividad 2
}
}
En general, el paralelismo en acciones independientes entre sí permite ahorrar mucho tiempo. Este es obviamente el caso cuando se procesa un workflow.
Así, un primer proceso dura una media de 20 segundos, y un segundo, de 40 segundos. Esto da como resultado un tiempo de procesamiento de 1 minuto:
PS > workflow Test-WfwPara {
Start-Sleep -Second 20
Start-Sleep -Second 40
}
PS > Measure-Command { Test-WfwPara }
Days : 0
Hours : 0
Minutes : 1
Seconds : 0
Milliseconds : 750
Ticks : 607502613
TotalDays : 0,000703128024305556
TotalHours : 0,0168750725833333
TotalMinutes : 1,012504355
TotalSeconds : 60,7502613
TotalMilliseconds : 60750,2613
Se introduce ahora la instrucción parallel:
PS > workflow Test-WfwPara {
parallel {
Start-Sleep...
Puntos de sincronización
Un workflow puede guardarse en disco para conservar su progreso. De este modo, si se produce un problema inesperado, es posible reanudar el workflows donde se guardó por última vez. Los imprevistos pueden incluir reinicios, interrupciones de red o incluso cortes eléctricos importantes.
Estas copias de seguridad se denominan puntos de control (checkpoints). Para quienes están familiarizados con la virtualización Hyper-V, este término resulta familiar. Es una instantánea del disco de una máquina virtual en un momento dado. Para un workflow, es prácticamente lo mismo. El workflow se escribe en la carpeta Appdata del usuario que ejecuta el workflow. El árbol completo es $env:LocalAppData\Microsoft\Windows\PowerShell\ WF\PS\. Los checkpoints se guardan en archivos con formato XML. Estos se eliminan cuando el workflow se completa o se elimina.
Los checkpoints se gestionan mediante tres elementos. El primero es el comando Checkpoint-Workflow, que se sitúa dentro del workflow. Solicita al flujo de trabajo que cree un punto de control y lo escriba en disco. En el siguiente ejemplo, la funcionalidad Hyper-V se activa en un cliente Windows, al igual que la funcionalidad HostGuardian. Entre estas dos acciones, se genera un punto de control.
Ejemplo de sintaxis
PS > workflow EnableHyperV {
Enable-WindowsOptionalFeature -FeatureName Microsoft-Hyper-V ...
Suspensión de un workflow
En el capítulo Jobs y paralelismo, se explicó el concepto de estado suspendido de un job. Esto solo es aplicable cuando el trabajo es de tipo PSWorkflowJob. Para que un workflow entre en estado Suspended, existen dos posibilidades. La primera consiste en utilizar el comando Suspend-Job directamente en el job del flujo de trabajo actual.
Ejemplo de sintaxis
PS > workflow Test-WfwSuspend {
Foreach ($num in 1..10) {
$num
CheckPoint-Workflow
Start-Sleep -Seconds $num
}
}
PS > $WorkflowJob = Test-WfwSuspend -AsJob
PS > Suspend-Job -Job $WorkflowJob
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
3 Job3 PSWorkflowJob Suspending True localhost Test-...
El uso del comando Suspend-Job requiere que el workflow se inicie como un job utilizando el parámetro...
Reiniciar un workflow (tras una suspensión o un crash)
Después de suspender un workflow, generalmente se desea reanudar su ejecución. Esto se hace utilizando el comando Resume-Job. Este comando, al igual que Suspend-Job, solo se puede utilizar con trabajos de tipo PSWorkflowJob. Para recuperar los diferentes Jobs de un workflow, se puede llamar directamente al comando Get-Job:
PS > Get-Job
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
3 Job3 PSWorkflowJob Suspending True localhost Test-...
5 Job5 PSWorkflowJob Suspending True localhost Test-...
Ahora estamos intentando relanzar el segundo trabajo:
PS > Get-Job -ID 5 | Resume-Job
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
5 Job5 PSWorkflowJob Running True localhost Test-......
Observación del contenido de un workflow
Como se mencionó al principio de este capítulo, los workflows se representan en forma XAML. Es posible conocer dicha estructura, ya que está contenida en una propiedad del objeto del flujo de trabajo. Para recuperar este objeto, se utiliza el comando Get-Command y luego apunte a la propiedad de interés. En este caso, es XamlDefinition. Volvamos a nuestro primer ejemplo para evitar una visualización demasiado compleja de entender:
workflow Demo-Workflow {
Write-Output "I am a flow"
}
A continuación, utilice el comando Get-Command:
PS > Get-Command Demo-Workflow
CommandType Name Version Source
----------- ---- ------- ------
workflow Demo-Workflow
A continuación, se refina la visualización para mostrar el código XAML:
PS > Get-Command Demo-Workflow | Foreach-Object XamlDefinition
<Activity
x:Class="Microsoft.PowerShell.DynamicActivities.Activity_..."
xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activ..."
xmlns:sad="clr-namespace:System.Activities.Debugger;assem..." ...
Integración en un módulo
Los workflows se declaran del mismo modo que las funciones. Por lo tanto, no es de extrañar que también puedan definirse dentro de un módulo. El proceso es idéntico al utilizado para una función. Basta con añadir la declaración del workflow en el archivo PSM1 del módulo. Para más información sobre cómo crear un módulo, consulte el capítulo Creación de módulos.
Ejemplo de contenido de un archivo PSM1
PS > Get-Content ./MyModule.psm1
workflow Demo-Workflow {
Write-Output "I am a flow"
}
Para utilizar el workflow, basta con importar el módulo y ejecutar el comando:
PS > Import-Module ./MyModule.psm1
PS > Demo-Workflow
I am a flow
Workflow: ¿para quién? ¿por qué?
Los workflows son una herramienta maravillosa, a pesar de la complejidad de su implementación y de las limitaciones que conllevan. Sin embargo, hoy en día podemos cuestionar seriamente su utilidad, especialmente con herramientas como DSC (véase el capítulo Desired State Configuration (DSC)) que permiten gestionar la configuración de sistemas con soporte de reinicio. Además, la versión 6.0 Core de PowerShell no incluye workflows. Los desarrolladores tuvieron que tomar una decisión al trasladar la solución al mundo libre y optaron por dejarlos fuera.
Por todo ello, es aconsejable utilizar workflows solo en casos concretos, para evitar contratiempos:
-
Cuando la ejecución del proceso supere las 6 horas.
-
Cuando exista riesgo de interrupciones por fallos de red o reinicios inesperados.
-
Cuando se requiere un alto grado de paralelismo y secuenciación de acciones.
-
Cuando no existe una alternativa más simple o moderna que resuelva el mismo problema.
Tenga en cuenta, sin embargo, que un workflow pasa por un proceso complejo antes de ejecutarse realmente. Por ejemplo, utilizar un workflow para recuperar la lista de servicios de varias máquinas no es eficiente. Preferimos utilizar PSRemoteJob para esto. Su activación es mucho más rápida, porque no se necesita la compilación en XAML. En resumen, evite...