Skopiuj plik zdalnie za pomocą PowerShell

95

Piszę skrypt PowerShell, który chcę uruchomić z serwera A. Chcę połączyć się z serwerem B i skopiować plik na serwer A jako kopię zapasową.

Jeśli nie można tego zrobić, chciałbym połączyć się z serwerem B z serwera A i skopiować plik do innego katalogu na serwerze B.

Widzę Copy-Itempolecenie, ale nie wiem, jak nadać mu nazwę komputera.

Myślałem, że mógłbym zrobić coś takiego

Copy-Item -ComputerName ServerB -Path C:\Programs\temp\test.txt -Destination (not sure how it would know to use ServerB or ServerA)

Jak mogę to zrobić?

chobo2
źródło
4
Aby użyć elementu do kopiowania, musisz użyć ścieżki UNC, takiej jak „\\ ServerB \ C $ \ Programs \ temp \ test.txt”

Odpowiedzi:

97

Po prostu użyj udziałów administracyjnych, aby skopiować pliki między systemami. W ten sposób jest o wiele łatwiej.

Copy-Item -Path \\serverb\c$\programs\temp\test.txt -Destination \\servera\c$\programs\temp\test.txt;

Używając ścieżek UNC zamiast ścieżek lokalnego systemu plików, pomagasz upewnić się, że skrypt jest wykonywalny z dowolnego systemu klienckiego, który ma dostęp do tych ścieżek UNC. Jeśli korzystasz ze ścieżek lokalnego systemu plików, masz zamiar uruchomić skrypt na określonym komputerze.

Działa to tylko wtedy, gdy sesja programu PowerShell jest uruchomiona przez użytkownika, który ma prawa do obu udziałów administracyjnych.

Sugeruję użycie zwykłego udziału sieciowego na serwerze B z dostępem tylko do odczytu dla wszystkich i po prostu zadzwoń (z serwera A):

Copy-Item -Path "\\\ServerB\SharedPathToSourceFile" -Destination "$Env:USERPROFILE" -Force -PassThru -Verbose
Trevor Sullivan
źródło
9
Jednym z możliwych problemów z tym podejściem jest to, że element kopiujący nie obsługuje alternatywnych poświadczeń (jeśli musisz uruchomić polecenie z innym użytkownikiem). W takim przypadku wymagane jest podejście New-PSDrive.
Jordania
1
To rozwiązanie działa tylko wtedy, gdy nie ma zapory między hostami blokującymi udziały UNC. W takim przypadku prawidłowe rozwiązanie znajduje się poniżej ( Copy-Item -FromSession).
Marc
88

Począwszy od wersji 5 programu PowerShell (zawartego w systemie Windows Server 2016, do pobrania jako część programu WMF 5 dla wcześniejszych wersji ) jest to możliwe dzięki zdalnej obsłudze. Zaletą tego jest to, że działa, nawet jeśli z jakiegokolwiek powodu nie możesz uzyskać dostępu do udziałów.

Aby to zadziałało, sesja lokalna, w której inicjowane jest kopiowanie, musi mieć zainstalowany program PowerShell 5 lub nowszy. Sesja zdalna nie musi mieć zainstalowanego programu PowerShell 5 - działa z wersjami PowerShell tak niskimi jak 2 i wersjami Windows Server tak niskimi, jak 2008 R2. [1]

Z serwera A utwórz sesję na serwerze B:

$b = New-PSSession B

A potem jeszcze z A:

Copy-Item -FromSession $b C:\Programs\temp\test.txt -Destination C:\Programs\temp\test.txt

Kopiowanie elementów do B odbywa się za pomocą -ToSession. Zwróć uwagę, że ścieżki lokalne są używane w obu przypadkach; musisz śledzić, na jakim serwerze jesteś.


[1]: podczas kopiowania z lub na zdalny serwer, który ma tylko PowerShell 2, uważaj na ten błąd w PowerShell 5.1 , który w momencie pisania oznacza, że ​​rekurencyjne kopiowanie plików nie działa -ToSession, najwyraźniej kopiowanie nie działa wszystko z -FromSession.

Jeroen Mostert
źródło
3
Stwierdziłem, że nie jest konieczne, aby oba serwery miały zainstalowane PS 5. Właśnie przeprowadziłem udany test, w którym tylko serwer źródłowy (Windows 10) miał zainstalowany PS 5. Celem był system Windows Server 2012 R2 z zainstalowanym domyślnym PS (raporty $ PSVersionTable.PSVersion 4).
Taylor Buchanan
2
Jeśli używasz -ToSession na źródle, tylko źródło wymaga zainstalowania PS 5. Jeśli używasz -FromSession w miejscu docelowym, tylko cel wymaga zainstalowania PS 5.
Taylor Buchanan
1
Działa to również, gdy masz zainstalowany tylko Hypervisor (bez serwera), nie ma potrzeby konfigurowania udziałów, wystarczy skorzystać z sesji!
dashesy
Dziękuję Ci! Ładne, eleganckie rozwiązanie, podobnie jak scpna sshLinux ... nie trzeba męczyć się z akcji brzydkie!
Tobias J
40

Użyj net uselub, New-PSDriveaby utworzyć nowy dysk:

New-PsDrive: utwórz nowy PsDrive widoczny tylko w środowisku PowerShell:

New-PSDrive -Name Y -PSProvider filesystem -Root \\ServerName\Share
Copy-Item BigFile Y:\BigFileCopy

Wykorzystanie sieci: utwórz nowy dysk widoczny we wszystkich częściach systemu operacyjnego.

Net use y: \\ServerName\Share
Copy-Item BigFile Y:\BigFileCopy
JPBlanc
źródło
Jeśli uruchomię to dwukrotnie, otrzymuję New-PSDrive : A specified logon session does not exist. It may already have been terminated-> Myślę, że poprzednia sesja nadal trwa -> Więc próbowałem użyć Remove-PSDrive-> nadal nie działa. Też net use <driveLetter> /deletenie pomogło. Czy mogę jeszcze coś zrobić, aby móc uruchomić to polecenie w konfiguracji kompilacji oprogramowania?
Bruno Bieri
Nie ma sensu biegać New-PSDrivedwa razy, co powinieneśA drive with the name 'Y' already exists.
JPBlanc
Zgadzam się, że nie ma sensu uruchamiać go dwukrotnie. Ale jest włączony do etapu kompilacji, a kompilacja jest uruchamiana kilka razy dziennie. Więc moim podejściem było usunięcie dysku, gdy wykonałem pracę, której potrzebowałem, i założyłem, że odtworzenie go po wykonaniu nowej kompilacji nie będzie problemem. Ale wydaje się to problemem. Jakaś inna wskazówka?
Bruno Bieri
A co z testowaniem, czy jest zamontowany przed zamontowaniem? lub możesz użyć Remove-PSDrive w swoim skrypcie, jeśli masz pewność, że wszystkie uchwyty używające tej ścieżki są zamknięte.
JPBlanc
16

Na wypadek, gdyby zdalny plik wymagał Twojego poświadczenia, aby uzyskać do niego dostęp, możesz wygenerować obiekt System.Net.WebClient za pomocą polecenia cmdlet New-Object do „Kopiuj plik zdalnie”, na przykład

$Source = "\\192.168.x.x\somefile.txt"
$Dest   = "C:\Users\user\somefile.txt"
$Username = "username"
$Password = "password"

$WebClient = New-Object System.Net.WebClient
$WebClient.Credentials = New-Object System.Net.NetworkCredential($Username, $Password)

$WebClient.DownloadFile($Source, $Dest)

Lub jeśli chcesz przesłać plik, możesz użyć UploadFile:

$Dest = "\\192.168.x.x\somefile.txt"
$Source   = "C:\Users\user\somefile.txt"

$WebClient.UploadFile($Dest, $Source)
Shyan1
źródło
1
@klm_ Czy możesz wyjaśnić, co masz na myśli?
FastTrack
0

Żadna z powyższych odpowiedzi nie zadziałała dla mnie. Ciągle otrzymuję ten błąd:

Copy-Item : Access is denied
+ CategoryInfo          : PermissionDenied: (\\192.168.1.100\Shared\test.txt:String) [Copy-Item], UnauthorizedAccessException>   
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.CopyItemCommand

Więc to zrobiło to dla mnie:

netsh advfirewall firewall set rule group="File and Printer Sharing" new enable=yes

Następnie z mojego hosta moja maszyna w polu Uruchom właśnie zrobiłem to:

\\{IP address of nanoserver}\C$
RogerW
źródło
1
Możliwe, że napotkasz problemy z uprawnieniami do udostępniania + systemu plików. Pamiętaj, że wygrywają najbardziej restrykcyjne uprawnienia, więc nawet jeśli masz dostęp w warstwie systemu plików NTFS, jeśli uprawnienia udziału Cię ograniczają, nie będziesz mógł pisać. :)
Trevor Sullivan