Copie o arquivo remotamente com PowerShell

94

Estou escrevendo um script do PowerShell que desejo executar do Servidor A. Desejo me conectar ao Servidor B e copiar um arquivo para o Servidor A como backup.

Se isso não puder ser feito, gostaria de me conectar ao Servidor B do Servidor A e copiar um arquivo para outro diretório no Servidor B.

Eu vejo o Copy-Itemcomando, mas não vejo como dar a ele um nome de computador.

Eu teria pensado que poderia fazer algo como

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

Como posso fazer isso?

chobo2
fonte
4
Para usar Copy-Item, você terá que usar um caminho UNC como "\\ ServerB \ C $ \ Programs \ temp \ test.txt"

Respostas:

95

Basta usar os compartilhamentos administrativos para copiar arquivos entre sistemas. É muito mais fácil assim.

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

Usando caminhos UNC em vez de caminhos de sistema de arquivos locais, você ajuda a garantir que seu script seja executável de qualquer sistema cliente com acesso a esses caminhos UNC. Se você usar caminhos de sistema de arquivos locais, estará se preparando para executar o script em um computador específico.

Isso só funciona quando uma sessão do PowerShell é executada sob o usuário que tem direitos para ambos os compartilhamentos administrativos.

Eu sugiro usar compartilhamento de rede regular no servidor B com acesso somente leitura para todos e simplesmente chamar (do Servidor A):

Copy-Item -Path "\\\ServerB\SharedPathToSourceFile" -Destination "$Env:USERPROFILE" -Force -PassThru -Verbose
Trevor Sullivan
fonte
9
Um possível problema com essa abordagem é que Copy-Item não oferece suporte a credenciais alternativas (se você tiver que executar o comando com um usuário diferente). Nesse caso, a abordagem New-PSDrive é necessária.
Jordan
1
Esta solução só funciona se não houver firewall entre os hosts bloqueando compartilhamentos UNC. Nesse caso, a solução correta está abaixo ( Copy-Item -FromSession).
Marc
85

Do PowerShell versão 5 em diante (incluído no Windows Server 2016, para download como parte do WMF 5 para versões anteriores ), isso é possível com remoting. A vantagem disso é que funciona mesmo se, por qualquer motivo, você não puder acessar os compartilhamentos.

Para que isso funcione, a sessão local onde a cópia é iniciada deve ter o PowerShell 5 ou superior instalado. A sessão remota não precisa ter o PowerShell 5 instalado - funciona com versões do PowerShell tão baixas quanto 2 e versões do Windows Server tão baixas quanto 2008 R2. [1]

No servidor A, crie uma sessão para o servidor B:

$b = New-PSSession B

E então, ainda de A:

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

A cópia de itens para B é feita com -ToSession. Observe que os caminhos locais são usados ​​em ambos os casos; você tem que controlar em qual servidor você está.


[1]: ao copiar de ou para um servidor remoto que tem apenas PowerShell 2, cuidado com este bug no PowerShell 5.1 , que no momento da escrita significa que a cópia recursiva de arquivo não funciona com -ToSession, uma cópia aparentemente não funciona em todos com -FromSession.

Jeroen Mostert
fonte
3
Descobri que não é necessário que ambos os servidores tenham o PS 5 instalado. Acabei de realizar um teste bem-sucedido onde apenas o servidor de origem (Windows 10) tinha o PS 5 instalado. O destino era o Windows Server 2012 R2 com PS padrão instalado (relatórios $ PSVersionTable.PSVersion 4).
Taylor Buchanan,
2
Se você usar -ToSession na fonte, apenas a fonte precisa do PS 5 instalado. Se você usar -FromSession no destino, apenas o destino precisa do PS 5 instalado.
Taylor Buchanan
1
Isso também funciona quando você tem apenas o Hypervisor instalado (sem servidor), não há necessidade de configurar compartilhamentos, apenas use as sessões!
precipitado
Obrigado! Bom, solução elegante, semelhante a scpmais sshno Linux ... não há necessidade de se preocupar com ações traquinas!
Tobias J
40

Use net useou New-PSDrivepara criar uma nova unidade:

New-PsDrive: crie um novo PsDrive visível apenas no ambiente PowerShell:

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

Uso líquido: crie uma nova unidade visível em todas as partes do sistema operacional.

Net use y: \\ServerName\Share
Copy-Item BigFile Y:\BigFileCopy
JPBlanc
fonte
Se eu executar isso duas vezes, recebo New-PSDrive : A specified logon session does not exist. It may already have been terminated-> Acho que uma sessão anterior ainda está em andamento -> Então tentei usar Remove-PSDrive-> ainda não funciona. Também net use <driveLetter> /deletenão ajudou. Posso fazer mais alguma coisa para executar este comando em uma configuração de compilação de software?
Bruno Bieri
Não faz sentido correr New-PSDriveduas vezes que deveriaA drive with the name 'Y' already exists.
JPBlanc
Concordo que não faz sentido executá-lo duas vezes. Mas é incorporado a uma etapa de construção e a construção é executada várias vezes ao dia. Portanto, minha abordagem foi remover a unidade assim que fizesse o trabalho de que precisava e presumia que não haveria problema em recriá-la quando uma nova execução de compilação acontecesse. Mas parece um problema. Alguma outra dica?
Bruno Bieri
Que tal testar se ele está montado antes de montá-lo? ou você pode usar Remove-PSDrive em seu script quando tiver certeza de que todos os identificadores que usam esse caminho estão fechados.
JPBlanc
16

Apenas no caso de o arquivo remoto precisar de sua credencial para ser acessado, você pode gerar um objeto System.Net.WebClient usando o cmdlet New-Object para "Copiar arquivo remotamente", assim

$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)

Ou se precisar fazer upload de um arquivo, você pode usar UploadFile:

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

$WebClient.UploadFile($Dest, $Source)
shyan1
fonte
1
@klm_ Você pode explicar o que quer dizer?
FastTrack de
0

Nenhuma das respostas acima funcionou para mim. Continuei recebendo este erro:

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

Então isso fez por mim:

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

Então, de meu host, minha máquina na caixa Executar, acabei de fazer isso:

\\{IP address of nanoserver}\C$
RogerW
fonte
1
Provavelmente, você teve problemas com as permissões de compartilhamento + sistema de arquivos. Lembre-se de que as permissões mais restritivas vencem, portanto, mesmo que você tenha acesso na camada do sistema de arquivos NTFS, se as permissões de compartilhamento o restringirem, você não poderá escrever. :)
Trevor Sullivan