Je développe un module PowerShell personnalisé, que j'aimerais utiliser dans le contexte d'une session distante sur un autre ordinateur. Le code suivant (qui ne fonctionne évidemment pas) explique ce que j'essaie de réaliser:
import-module .\MyCustomModule.psm1
$session = new-pssession -computerName server01
invoke-command -session $session -scriptblock {
<# use function defined in MyCustomModule here #>
}
La première question est de savoir s'il est possible de réaliser ce scénario? Je veux simplement que mon module personnalisé soit physiquement présent sur ma machine, pas sur le serveur distant.
J'ai trouvé ce fil , mais je n'ai pas réussi à le faire fonctionner - il ne permet pas de créer une session de la machine distante vers la locale. J'ai probablement dû faire face aux limitations de configuration mentionnées quelque part dans les commentaires de ce fil ... En outre, l'auteur a mentionné les implications en termes de performances, ce qui est essentiel pour ma solution ...
Si c'est possible, alors comment?
La version de PowerShell n'est actuellement pas une contrainte - si la solution n'est disponible que sur PS 3.0 - je peux vivre avec.
Il y a eu d'excellents commentaires sur la question, et j'ai passé un certain temps à étudier différentes façons d'aborder le problème.
Pour commencer, ce que j'ai demandé initialement n'est pas possible. Je veux dire, si vous suivez la voie du module, alors le module devrait être physiquement présent sur une machine cible pour pouvoir Import-Module
en session distante.
Pour résumer davantage ma question, j'essaie de créer un cadre réutilisable basé sur PowerShell pour les déploiements de produits. Ce sera un déploiement de manière Push, ce qui signifie que nous encourageons les gens à exécuter certains scripts sur une machine locale pour les déployer sur un serveur distant. Dans la mesure où j'ai exploré la région, il y a deux manières possibles qui sont amicales au bon sens.
Le processus à suivre:
*.psm1
)PSModulePath
pour inclure l'emplacement du nouveau moduleInvoke-Command -Session $s -ScriptBlock {...}
Import-Module CustomModule
- il recherchera le CustomModule
sur une machine distante et le trouvera évidemmentVoici les raisons d'aimer cette approche:
Les éléments suivants sont importants à prendre en considération:
xcopy
du partage dossier. En outre, le mécanisme de livraison devrait prendre en charge les installations de mise à niveau/rétrogradation et (de préférence) multi-instances, mais cela est plus lié à ma tâche qu'au problème en généralLe processus à suivre:
Invoke-Command -Session $s -FilePath .\myscript.ps1
pour charger les fonctions définies dans un script dans la session distanteInvoke-Command -Session $s -ScriptBlock {...}
et faites référence à vos fonctions personnalisées - elles seront présentes dans une sessionVoici les bons points de cette approche:
Bien sûr, ce n'est pas idéal:
Enfin, je dois dire que la machine distante doit encore être préparée pour la télécommande. Voici ce que je veux dire:
Set-ExecutionPolicy Unrestricted
Enable-PSRemoting
Voici une autre approche: recréez le module dans une session distante, sans copier aucun fichier.
Je n'ai fait aucune tentative pour gérer les dépendances entre les modules, mais cela semble fonctionner correctement pour les modules autonomes simples. Il repose sur la disponibilité du module dans la session locale, car cela facilite la détermination des exportations, mais avec un peu de travail supplémentaire, il fonctionnerait également avec un fichier de module.
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;
}
Je ne crois pas que cela soit pris en charge à droite de la boîte sans aucun "piratage". La décision intelligente serait probablement de placer le module sur un emplacement public comme un serveur de fichiers et de l'importer sur le serveur lorsque vous en avez besoin. 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 #>
}
Merci pour ce fil, c'était utile….
Mais j'ai en fait réécrit la fonction.
Sachez que la fonction d'origine dans cet article ou cette fonction réécrite comprend des données de manifeste de module. Vous ne pouvez donc pas vous fier aux vérifications de version du module.
function Import-ModuleRemotely {
Param (
[string] $moduleName,
[System.Management.Automation.Runspaces.PSSession] $session
)
Import-Module $moduleName
$Script = @"
if (get-module $moduleName)
{
remove-module $moduleName;
}
New-Module -Name $moduleName { $($(Get-Module $moduleName).Definition) } | Import-Module
"@
Invoke-Command -Session $Session -ScriptBlock {
Param($Script)
. ([ScriptBlock]::Create($Script))
Get-Module
} -ArgumentList $Script
}
Qu'en est-il de créer un bloc de script à partir de votre fonction personnalisée et de l'envoyer aux serveurs cibles à l'aide de Invoke-command
Import-module YourModule
$s = [scriptblock]::Create($(get-item Function:\Your-ModuleFunction).Definition)
Invoke-Command -ScriptBlock $s -Computername s1,s2,sn