2012-05-17 16 views
19

Właśnie wypaliłem kilka godzin szukając rozwiązania do wysyłania plików przez aktywną PSSession. A rezultatem jest nada, niente. Próbuję wywołać polecenie na komputerze zdalnym za pośrednictwem aktywnej sesji, która powinna skopiować coś z pamięci sieciowej. Tak w zasadzie to jest to:Wysyłaj pliki przez PSSession

icm -Session $s { 
Copy-Item $networkLocation $PCLocation } 

powodu problemu „drugi hop”, nie mogę tego zrobić bezpośrednio, a ponieważ używam serwera wygrana 2003 Nie mogę włączyć CredSSP. Mogę najpierw skopiować pliki na mój komputer, a następnie wysłać/wypchnąć je na zdalny komputer, ale jak? Próbowałem PModem, ale jak widziałem, może pobierać dane, a nie naciskać.

Każda pomoc jest doceniana.

+1

Dlaczego nie używasz udziału sieciowego do kopiowania plików? – JPBlanc

+1

Dobrze, ale wyższe autorytety tego nie akceptują :) –

+1

Jeśli możesz włączyć komputer zdalny jako "Zaufany dla delegacji" w AD, możesz wykonać drugi skok bez CredSSP. –

Odpowiedz

17

Jeśli był to mały plik, można wysłać zawartość pliku i nazwę pliku jako parametry.

$f="the filename" 
$c=Get-Content $f 
invoke-command -session $s -script {param($filename,$contents) ` 
    set-content -path $filename -value $contents} -argumentlist $f,$c 

Jeśli plik jest zbyt długi, aby zmieścić się w cokolwiek limity sesji są, można odczytać plik w jak kawałki i zastosować podobną technikę do nich dołączyć razem w miejscu docelowym

+1

'$ f == $ nazwa_pliku' i' $ c == $ zawartość' ?? –

+2

$ filename i $ contents są nazwami parametrów w bloku skryptowym. $ f i $ c są zmiennymi, które są przekazywane do bloku skryptów. –

2

Ostatnio miałem do czynienia z tym samym problemem i przedstawiłem dowód na to, jak przesyłać pliki przez sesję PS Remoting. Znajdziesz skrypt tutaj:

https://gist.github.com/791112

#requires -version 2.0 

[CmdletBinding()] 
param (
    [Parameter(Mandatory=$true)] 
    [string] 
    $ComputerName, 

    [Parameter(Mandatory=$true)] 
    [string] 
    $Path, 

    [Parameter(Mandatory=$true)] 
    [string] 
    $Destination, 

    [int] 
    $TransferChunkSize = 0x10000 
) 

function Initialize-TempScript ($Path) { 
    "<# DATA" | Set-Content -Path $Path 
} 

function Complete-Chunk() { 
@" 
DATA #> 
`$TransferPath = `$Env:TEMP | Join-Path -ChildPath '$TransferId' 
`$InData = `$false 
`$WriteStream = [IO.File]::OpenWrite(`$TransferPath) 
try { 
    `$WriteStream.Seek(0, 'End') | Out-Null 
    `$MyInvocation.MyCommand.Definition -split "``n" | ForEach-Object { 
     if (`$InData) { 
      `$InData = -not `$_.StartsWith('DATA #>') 
      if (`$InData) { 
       `$WriteBuffer = [Convert]::FromBase64String(`$_) 
       `$WriteStream.Write(`$WriteBuffer, 0, `$WriteBuffer.Length) 
      } 
     } else { 
      `$InData = `$_.StartsWith('<# DATA') 
     } 
    } 
} finally { 
    `$WriteStream.Close() 
} 
"@ 
} 

function Complete-FinalChunk ($Destination) { 
@" 
`$TransferPath | Move-Item -Destination '$Destination' -Force 
"@ 
} 

$ErrorActionPreference = 'Stop' 
Set-StrictMode -Version Latest 

$EncodingChunkSize = 57 * 100 
if ($EncodingChunkSize % 57 -ne 0) { 
    throw "EncodingChunkSize must be a multiple of 57" 
} 

$TransferId = [Guid]::NewGuid().ToString() 


$Path = ($Path | Resolve-Path).ProviderPath 
$ReadBuffer = New-Object -TypeName byte[] -ArgumentList $EncodingChunkSize 

$TempPath = ([IO.Path]::GetTempFileName() | % { $_ | Move-Item -Destination "$_.ps1" -PassThru}).FullName 
$Session = New-PSSession -ComputerName $ComputerName 
$ReadStream = [IO.File]::OpenRead($Path) 

$ChunkCount = 0 
Initialize-TempScript -Path $TempPath 

try { 
    do { 
     $ReadCount = $ReadStream.Read($ReadBuffer, 0, $EncodingChunkSize) 
     if ($ReadCount -gt 0) { 
      [Convert]::ToBase64String($ReadBuffer, 0, $ReadCount, 'InsertLineBreaks') | 
       Add-Content -Path $TempPath 
     } 
     $ChunkCount += $ReadCount 
     if ($ChunkCount -ge $TransferChunkSize -or $ReadCount -eq 0) { 
      # send 
      Write-Verbose "Sending chunk $TransferIndex" 
      Complete-Chunk | Add-Content -Path $TempPath 
      if ($ReadCount -eq 0) { 
       Complete-FinalChunk -Destination $Destination | Add-Content -Path $TempPath 
       Write-Verbose "Sending final chunk" 
      } 
      Invoke-Command -Session $Session -FilePath $TempPath 

      # reset 
      $ChunkCount = 0 
      Initialize-TempScript -Path $TempPath 
     } 
    } while ($ReadCount -gt 0) 
} finally { 
    if ($ReadStream) { $ReadStream.Close() } 
    $Session | Remove-PSSession 
    $TempPath | Remove-Item 
} 

Kilka drobnych zmian pozwoliłoby przyjąć sesję jako parametr zamiast niego rozpoczynając nowy. Zauważyłem, że zużycie pamięci w usłudze Remoting na komputerze docelowym może znacznie wzrosnąć podczas przesyłania dużych plików. Podejrzewam, że PS Remoting nie był tak naprawdę zaprojektowany do użycia w ten sposób.

31

Jest to obecnie możliwe w PowerShell/WMF 5,0

Copy-Item ma -FromSession i -toSession parametry. Możesz użyć jednego z nich i przekazać zmienną sesji.

np.

$cs = New-PSSession -ComputerName 169.254.44.14 -Credential (Get-Credential) -Name SQL 
Copy-Item Northwind.* -Destination "C:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL2008R2\MSSQL\DATA\" -ToSession $cs 

Zobacz więcej przykładów na https://richardspowershellblog.wordpress.com/2015/05/28/copy-files-over-ps-remoting-sessions/

0
$data = Get-Content 'C:\file.exe' -Raw 
Invoke-Command -ComputerName 'server' -ScriptBlock { $using:data | Set-Content -Path 'D:\filecopy.exe' } 

Nie wiem, co faktycznie maksymalny rozmiar pliku to ograniczenie.

+0

Co to jest 'get-data'? – Mark

+0

To byłbym ja pisząc maszynę z wierzchu mojej głowy. Powinien być "Get-Content" oczywiście – mtnielsen

1

NET USE pozwala dodać literę dysku lokalnego do zdalnego systemu, który następnie następnie umożliwia korzystanie literę dysku w swoim PSSession, lub nawet bez PSSession. Jest to przydatne, jeśli nie masz Powershell v5.0, a nawet jeśli nie,

można użyć pilota zdalnego nazwę komputera lub jego adres IP w ramach zdalnego ścieżki UNC i można określić nazwę użytkownika i hasło uwierzytelniające na tej samej linii:

NET USE Z: \\192.168.1.50\ShareName /USER:192.168.1.50\UserName UserPassword 

Inny przykład:

NET USE Z: \\RemoteSystem\ShareName /USER:RemoteSystem\UserName UserPassword 

LUB

NET USE Z: \\RemoteSystem\ShareName /USER:Domain\UserName UserPassword 

Jeśli nie dostarczy kr użytkownika edentials na tej samej linii, użytkownik zostanie poproszony o nich:

>NET USE Z: \\192.168.1.50\ShareName 
Enter the user name for '192.168.1.50': 192.168.1.50\UserName 
Enter the password for 192.168.1.50: ***** 
The command completed successfully. 

Można usunąć literę dysku, gdy skończysz z poniższym:

NET USE Z: /delete 

można uzyskać pełną składnię z siatką POSŁUGIWAĆ SIĘ /?

>net use /? 
The syntax of this command is: 

NET USE 
[devicename | *] [\\computername\sharename[\volume] [password | *]] 
     [/USER:[domainname\]username] 
     [/USER:[dotted domain name\]username] 
     [/USER:[[email protected] domain name] 
     [/SMARTCARD] 
     [/SAVECRED] 
     [[/DELETE] | [/PERSISTENT:{YES | NO}]] 

NET USE {devicename | *} [password | *] /HOME 

NET USE [/PERSISTENT:{YES | NO}] 

NET to standardowa komenda zewnętrzny .exe w folderze systemowym i pracuje w PowerShell dobrze.

+0

Czy nie jest o wiele łatwiej po prostu zaktualizować swój PowerShell do wersji V5 +? – Liam

Powiązane problemy