別のコンピューターへのリモートセッションのコンテキストで使用したいカスタムPowerShellモジュールを開発しています。次のコード(明らかに機能しない)は、私が達成しようとしていることを説明しています。
import-module .\MyCustomModule.psm1
$session = new-pssession -computerName server01
invoke-command -session $session -scriptblock {
<# use function defined in MyCustomModule here #>
}
最初の質問は、このシナリオを実現できるかどうかです。つまり、カスタムサーバーのみをリモートサーバー上ではなく、マシン上に物理的に存在させたいのです。
このスレッド が見つかりましたが、動作するように管理していません。リモートマシンからローカルマシンに戻るセッションを作成できません。おそらく、私はそのスレッドへのコメントのどこかに言及されている構成の制限に直面していました...さらに、著者は私のソリューションにとって重要なパフォーマンスへの影響に言及しました...
それが可能なら、どうやって?
現在、PowerShellのバージョンは制約ではありません-ソリューションがPS 3.0でのみ利用可能な場合-私はこれで生きることができます。
この質問には素晴らしいコメントがいくつかあり、私はこの問題に取り組むためのさまざまな方法を調査するのに少し時間を費やしました。
そもそも、私が最初に求めたことは不可能です。つまり、モジュールを使用する場合、リモートセッションにImport-Module
できるように、モジュールはターゲットマシンに物理的に存在する必要があります。
さらに質問を抽象化するために、製品展開用の再利用可能なPowerShellベースのフレームワークを作成しようとしています。これはプッシュ型の展開になります。つまり、ローカルマシンでスクリプトを実行して、リモートサーバーに展開することをお勧めします。私がこの地域を調査した限りでは、常識にやさしい2つの方法があります。
従うべきプロセス:
*.psm1
)PSModulePath
変数を拡張して新しいモジュールの場所を含めるInvoke-Command -Session $s -ScriptBlock {...}
を使用しますImport-Module CustomModule
から開始-リモートマシンでCustomModule
を検索し、明らかにそれを見つけます以下は、このアプローチを愛する理由です。
以下を考慮することが重要です。
xcopy
など、他のオプションもありますフォルダ。また、配信メカニズムはアップグレード/ダウングレードおよび(できれば)マルチインスタンスインストールをサポートする必要がありますが、それは一般的な問題よりも私のタスクに関連しています従うべきプロセス:
Invoke-Command -Session $s -FilePath .\myscript.ps1
を使用して、スクリプトで定義された関数をリモートセッションに読み込みます。Invoke-Command -Session $s -ScriptBlock {...}
を使用して、カスタム関数を参照します-それらはセッション中に存在しますこのアプローチの良い点は次のとおりです。
もちろん、それは理想的ではありません。
最後に、リモート処理のためにリモートマシンを準備する必要があると言っておく必要があります。これは私が意味するものです:
Set-ExecutionPolicy Unrestricted
Enable-PSRemoting
別のアプローチを次に示します。ファイルをコピーせずに、リモートセッションでモジュールを再作成します。
私はモジュール間の依存関係に対処しようとしませんでしたが、これは単純な自己完結型モジュールに対してはうまくいくようです。ローカルセッションで使用可能なモジュールに依存します。これにより、エクスポートの決定が容易になりますが、少し余分な作業を行うと、モジュールファイルでも機能します。
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;
}
これは、「ハッキング」なしですぐにサポートされるとは思わない。モジュールをファイルサーバーなどの公共の場所に置き、必要なときにサーバーにインポートするのがおそらく賢明でしょう。例:
$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 #>
}
このスレッドをありがとう、それは役に立ちました…。
しかし、私は実際に関数を書き直しました。
この投稿の元の関数またはこの書き換えられた関数には、モジュールマニフェストデータが含まれていることに注意してください。したがって、モジュールのバージョンチェックに依存することはできません。
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
}
カスタム関数からスクリプトブロックを作成し、Invoke-command
を使用してターゲットサーバーに送信する方法について
Import-module YourModule
$s = [scriptblock]::Create($(get-item Function:\Your-ModuleFunction).Definition)
Invoke-Command -ScriptBlock $s -Computername s1,s2,sn