powershell powershell-v2.0 powershell-remoting powershell-v3.0

¿Cómo importar un módulo PowerShell personalizado en la sesión remota?



powershell-v2.0 powershell-remoting (4)

Estoy desarrollando un módulo PowerShell personalizado, que me gustaría usar en el contexto de una sesión remota en una computadora diferente. El siguiente código (que obviamente no funciona) explica lo que intento lograr:

import-module ./MyCustomModule.psm1 $session = new-pssession -computerName server01 invoke-command -session $session -scriptblock { <# use function defined in MyCustomModule here #> }

La primera pregunta es si es posible lograr este escenario. Quiero decir que solo me gustaría que mi módulo personalizado esté físicamente presente en mi máquina, no en el servidor remoto.

Encontré este hilo , pero no conseguí que funcionara; no permite crear una sesión desde la máquina remota a la local. Probablemente, me enfrenté a las limitaciones de configuración mencionadas en algún lugar de los comentarios a ese hilo ... Además, el autor mencionó las implicaciones de rendimiento que son críticas para mi solución ...

Si eso es posible, ¿cómo?

La versión de PowerShell actualmente no es una restricción, si la solución solo está disponible en PS 3.0, puedo vivir con esto.


¿Qué hay de hacer Scriptblock fuera de su función personalizada y enviarlo a los servidores de terget utilizando Invoke-command

Import-module YourModule $s = [scriptblock]::Create($(get-item Function:/Your-ModuleFunction).Definition) Invoke-Command -ScriptBlock $s -Computername s1,s2,sn


Aquí hay otro enfoque: vuelva a crear el módulo en una sesión remota, sin copiar ningún archivo.

No he intentado hacer frente a las dependencias entre los módulos, pero parece que funciona bien para los módulos simples y autónomos. Se basa en que el módulo esté disponible en la sesión local, ya que facilita la determinación de las exportaciones, pero con un poco de trabajo adicional también funcionaría con un archivo de módulo.

function Import-ModuleRemotely([string] $moduleName,[System.Management.Automation.Runspaces.PSSession] $session) { $localModule = get-module $moduleName; if (! $localModule) { write-warning "No local module by that name exists"; return; } function Exports([string] $paramName, $dictionary) { if ($dictionary.Keys.Count -gt 0) { $keys = $dictionary.Keys -join ","; return " -$paramName $keys" } } $fns = Exports "Function" $localModule.ExportedFunctions; $aliases = Exports "Alias" $localModule.ExportedAliases; $cmdlets = Exports "Cmdlet" $localModule.ExportedCmdlets; $vars = Exports "Variable" $localModule.ExportedVariables; $exports = "Export-ModuleMember $fns $aliases $cmdlets $vars;"; $moduleString= @" if (get-module $moduleName) { remove-module $moduleName; } New-Module -name $moduleName { $($localModule.Definition) $exports; } | import-module "@ $script = [ScriptBlock]::Create($moduleString); invoke-command -session $session -scriptblock $script; }


Hubo algunos excelentes comentarios a la pregunta, y he dedicado un tiempo a investigar diversas formas de abordar el problema.

Para empezar, lo que inicialmente pedí no es posible. Quiero decir, si va por el módulo, entonces el módulo debe estar presente físicamente en una máquina de destino para poder Import-Module a la sesión remota.

Para resumir más mi pregunta, intento crear un marco reutilizable basado en PowerShell para las implementaciones de productos. Serán implementaciones push-manner, lo que significa que alentamos a las personas a ejecutar algunos scripts en un equipo local para implementarlos en algún servidor remoto. En cuanto investigué el área, hay dos maneras posibles que son amigables con el sentido común.

Enfoque de los módulos

El proceso a seguir:

  • coloque cada pieza de funcionalidad lógicamente diferente en el módulo de PowerShell ( *.psm1 )
  • distribuya el módulo a la máquina remota y extienda la variable PSModulePath para incluir la ubicación de los nuevos módulos
  • en una máquina cliente, cree una nueva sesión en el servidor remoto y use Invoke-Command -Session $s -ScriptBlock {...}
  • en el bloque de secuencia de comandos, inicie desde Import-Module CustomModule ; buscará el CustomModule en una máquina remota y, obviamente, lo encontrará.

Ventajas

Las siguientes son las razones para amar este enfoque para:

  • la consecuencia del rol del módulo tradicional: facilitar la creación de bibliotecas reutilizables
  • de acuerdo con el gran libro de Windows PowerShell en acción , "los módulos se pueden usar para crear aplicaciones específicas de dominio". Por lo que yo entiendo, se puede lograr combinando el módulo anidando y mezclando secuencias de comandos / módulos binarios para exponer la interfaz intuitiva específica de un determinado dominio. Básicamente, este es el que más valoro para el objetivo del marco de implementación basado en PowerShell

Desventajas

Lo siguiente es importante tener en cuenta:

  • Debe encontrar la forma de entregar los módulos personalizados a la máquina remota. He jugado con NuGet , y no estoy seguro de que se adapte bien a la tarea, pero también hay otras opciones, por ejemplo, el instalador MSI o la xcopy simple desde la carpeta compartida. Además, el mecanismo de entrega debería ser compatible con la actualización / degradación y (preferiblemente) las instalaciones de varias instancias, pero eso está más relacionado con mi tarea que con el problema en general.

Guiones de enfoque

El proceso a seguir:

  • coloque cada pieza de funcionalidad lógicamente diferente en una secuencia de comandos de PowerShell separada (* .ps1)
  • en una máquina cliente, cree una nueva sesión en el servidor remoto y use Invoke-Command -Session $s -FilePath ./myscript.ps1 para cargar las funciones definidas en una secuencia de comandos a la sesión remota
  • use otro Invoke-Command -Session $s -ScriptBlock {...} y refiérase a sus funciones personalizadas; estarán allí en una sesión

Ventajas

Los siguientes son buenos puntos de este enfoque:

  • es simple: no es necesario que conozca las peculiaridades del módulo. Simplemente escriba scripts simples de PowerShell y eso es todo
  • no tiene que entregar nada a la máquina remota, esto hace que la solución sea aún más simple y menos propensa a errores en el mantenimiento

Desventajas

Claro, no es ideal:

  • hay menos control sobre la solución: por ejemplo, si "importa" un conjunto de funciones a la sesión, todas ellas son "importadas" y visibles para el usuario, por lo que no hay "encapsulación", etc. Estoy seguro de que hay muchas soluciones puede vivir con esto, por lo que no decida basarse solo en este punto
  • la funcionalidad en cada archivo debe ser independiente: cualquier fuente de puntos o importación de módulos desde allí buscará la máquina remota, no la local.

Finalmente, debería decir que la máquina remota aún necesita estar preparada para la comunicación remota. Esto es lo que quiero decir:

  • la política de ejecución debe cambiarse a algo, porque está restringida de manera predeterminada: Set-ExecutionPolicy Unrestricted
  • El acceso remoto de PowerShell debe estar habilitado: Enable-PSRemoting
  • la cuenta que ejecuta la secuencia de comandos debe agregarse a los administradores locales del servidor remoto
  • Si tiene previsto acceder a archivos compartidos en la sesión remota, asegúrese de conocer la autenticación de varios saltos y tomar las medidas adecuadas.
  • asegúrate de que tu antivirus sea tu amigo y no te envíe al infierno de PowerShell

No creo que esto se admita directamente de la caja sin ningún "hackeo". El movimiento inteligente probablemente sea poner el módulo en una ubicación pública como un servidor de archivos e importarlo en el servidor cuando lo necesite. Ex:

$session = new-pssession -computerName server01 invoke-command -session $session -scriptblock { #Set executionpolicy to bypass warnings IN THIS SESSION ONLY Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process #Import module from public location Import-Module //fileserver/folders/modulelocation... <# use function defined in MyCustomModule here #> }