Powershell Remoting: использование импортированных командлетов модуля в удаленном pssession
Есть ли способ использовать модули, которые были импортированы в локальный сеанс в удаленном сеансе? Я посмотрел на import-pssession, но я не знаю, как получить локальную сессию. Вот пример того, что я хочу сделать.
import-module .\MyModule\MyModule.ps1
$session = new-pssession -computerName RemoteComputer
invoke-command -session $session -scriptblock { Use-CmdletFromMyModule }
Кроме того, я не хочу импортировать модуль в удаленном сеансе, так как файлы ps1 не находятся на этом сервере.
Ответы
Ответ 1
Я закончил тем, что взломал это, чтобы работать. То, что я сделал, это создать локальный сеанс, импортировать модули в этот сеанс и использовать import-pssession для импорта модулей из созданного локального сеанса в удаленный сеанс. Это медленно. Если у кого-то есть лучший способ сделать это, или если кто-то знает, как получить экземпляр базового сеанса, я бы хотел услышать от вас!
Remoting.psm1
function Export-ModuleToSession {
Param(
[ValidateNotNull()]
$session,
[ValidateNotNull()]
$modules
)
$computername = $env:computername
$modulesToImport = get-module -name $modules
invoke-command -session $session -argumentlist @($computername, $modulesToImport) -scriptblock {
Param(
$computername,
$modules
)
write-host ("Creating Temp Session On: " + $computername)
$localSession = New-psSession -computername $computername
$modules | foreach-object {
if($_.ModuleType -ne "Binary") {
$path = $_.path
}
else {
$path = join-path (split-path $_.Path) ("{0}.psd1" -f $_.name)
}
invoke-command -session $localSession -argumentList $path -scriptblock {
Param(
$path
)
$initializeDefaultBTSDrive = $false
set-executionpolicy unrestricted
write-host ("Importing Module To Temp Session: " + $path)
import-module $path
}
}
$initializeDefaultBTSDrive = $false
$modules | foreach-object {
write-host ("Exporting Module: " + $_.name)
import-psSession -session $localSession -Module $_.name | out-null
}
}
}
MyModule.psm1
function MyCmdlet {}
RemotingTest.ps1
import-module .\remoting.psm1
import-module .\MyModule.psm1
try
{
$remoteSession = New-PsSession -computerName "RemoteComputer"
Export-ModuleToSession -session $remoteSession -modules "MyModule"
Invoke-Command -session $remoteSession -scriptblock { MyCmdlet } -verbose -ea Stop
}
finally
{
Remove-PsSession $remoteSession -ea Continue
Remove-Module "Remoting" -ea Continue
Remove-Module "MyModule" -ea Continue
}
Ответ 2
Как альтернатива тому, что упоминает Джонатан, если у вас есть исходные модули, которые вы хотите протащить по проводам, то вы можете сделать это без особых проблем. Если у вас есть двоичные файлы, вы можете сделать что-то подобное. Но я бы сказал, что все ставки там. По сути, вы перетаскиваете файлы как параметры в хэш, записываете в temp, а затем импортируете.
function Export-SourceModulesToSession
{
Param(
[Management.Automation.Runspaces.PSSession]
[ValidateNotNull()]
$Session,
[IO.FileInfo[]]
[ValidateNotNull()]
[ValidateScript(
{
(Test-Path $_) -and (!$_.PSIsContainer) -and ($_.Extension -eq '.psm1')
})]
$ModulePaths
)
$remoteModuleImportScript = {
Param($Modules)
Write-Host "Writing $($Modules.Count) modules to temporary disk location"
$Modules |
% {
$path = ([IO.Path]::GetTempFileName() + '.psm1')
$_.Contents | Out-File -FilePath $path -Force
"Importing module [$($_.Name)] from [$path]"
Import-Module $path
}
}
$modules = $ModulePaths | % { @{Name = $_.Name; Contents = Get-Content $_ } }
$params = @{
Session = $Session;
ScriptBlock = $remoteModuleImportScript;
Argumentlist = @(,$modules);
}
Invoke-Command @params
}
Вызов как
$session = New-PSSession -ComputerName Foo
Export-SourceModulesToSession $session -ModulePaths '.\module.psm1','.\module2.psm1'
Также теоретически возможно, экспортируя текущую локальную сессию в модуль и нажимая ее на непроверенный псевдопровод. Это может не сработать...
$localSession = New-PSSession #defaults to localhost
# if you don't have modules automatically loading in the profile, etc, then manually load them
Invoke-Command -Computer $localSession -ScriptBlock { Import-Module 'foo'; Import-Module '.\module.ps1' }
Export-PSSession $localSession -OutputModule TempLocalModule
#now that you have TempLocalModule written out, it possible you can send that thing across the wire in the same way
Ответ 3
если это помогает:
если вы можете переключиться на PowerShell 3.0, тогда
командлеты Get-Module и Import-Module поддерживают модули на удаленных компьютерах:
http://technet.microsoft.com/en-us/library/hh857339.aspx#BKMK_REM
Должно быть возможно запустить PowerShell на удаленном компьютере, который выполняет импорт-модуль,
без каких-либо сценариев ps1 на удаленном компьютере.
Ответ 4
Я не верю, что ты можешь. Вы можете пойти другим путем - импортировать команды, загруженные на удаленном компьютере, в ваш удаленный сеанс, запущенный на локальном компьютере. Вы можете указать команду script для вызова, и она скопирует этот script на удаленный компьютер и запустит его. Но если вам нужны snapins или дополнительные модули, вам нужно будет убедиться, что они установлены на каждом удаленном компьютере, а затем загрузите их в удаленный сеанс с помощью команд или вашего script.
Ответ 5
Я бы предложил что-то вроде:
$rs = New-PSSession -ComputerName "RemoteComputer"
Invoke-Command -Session $rs -scriptblock {import-module ActiveDirectory}
Import-PSSession -Session $rs -Module ActiveDirectory
С тех пор вы можете использовать командлеты ActiveDirectory в сеансе.
Надеюсь, что это поможет.
Ответ 6
Итак, я искал что-то подобное... В моем случае мне просто нужно было экспортировать одну функцию на удаленную сессию... вот что я придумал. Может быть, вы могли бы перевернуть его, чтобы попробовать. Он не работает с внутренними командами, но он работает с функциями в пользовательских модулях (в тестировании, которое я сделал).
function Export-FunctionToSession
{
[CmdletBinding()]
[Alias()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$Session,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$FunctionName
)
$script = "Function $functionName(){" + (Get-Command $functionName).definition + '}'
$scriptBlock = {Invoke-Expression $using:script}
Invoke-Command -Session $session -ScriptBlock $scriptBlock
}
Ответ 7
использовать аутентификацию credssp
invoke-command -computername $localSession -Credential $Credential -Authentication Credssp