Copiar archivo de forma remota con PowerShell

94

Estoy escribiendo un PowerShell script de que quiero ejecutar desde el servidor A. Quiero conectarme al servidor B y copiar un archivo al servidor A como copia de seguridad.

Si eso no se puede hacer, me gustaría conectarme al servidor B desde el servidor A y copiar un archivo a otro directorio en el servidor B.

veo el Copy-Item comando, pero no veo cómo darle un nombre de computadora.

Hubiera pensado que podría hacer algo como

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

¿Cómo puedo hacer esto?

chobo2
fuente
4
Para usar Copy-Item, tendrá que usar una ruta UNC como "\\ ServerB \ C $ \ Programs \ temp \ test.txt"

Respuestas:

96

Simplemente use los recursos compartidos administrativos para copiar archivos entre sistemas. De esta forma es mucho más fácil.

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

Al utilizar rutas UNC en lugar de rutas locales del sistema de archivos, ayuda a garantizar que su script sea ejecutable desde cualquier sistema cliente con acceso a esas rutas UNC. Si usa las rutas del sistema de archivos local, entonces se está arrinconando para ejecutar el script en una computadora específica.

Esto solo funciona cuando se ejecuta una sesión de PowerShell con el usuario que tiene derechos sobre ambos recursos compartidos administrativos.

Sugiero usar un recurso compartido de red regular en el servidor B con acceso de solo lectura para todos y simplemente llamar (desde el servidor A):

Copy-Item -Path "\\\ServerB\SharedPathToSourceFile" -Destination "$Env:USERPROFILE" -Force -PassThru -Verbose
Trevor Sullivan
fuente
9
Un posible problema con este enfoque es que Copy-Item no admite credenciales alternativas (si tiene que ejecutar el comando con un usuario diferente). En ese caso, se requiere el enfoque New-PSDrive.
Jordania
1
Esta solución solo funciona si no hay un firewall entre los hosts que bloqueen los recursos compartidos UNC. En ese caso, la solución correcta está debajo ( Copy-Item -FromSession).
Marc
85

De PowerShell versión 5 en adelante (incluido en Windows Server 2016, descargable como parte de WMF 5 para versiones anteriores ), esto es posible con la comunicación remota. El beneficio de esto es que funciona incluso si, por cualquier motivo, no puede acceder a los recursos compartidos.

Para que esto funcione, la sesión local donde se inicia la copia debe tener instalado PowerShell 5 o superior. La sesión remota no necesita tener instalado PowerShell 5; funciona con versiones de PowerShell tan bajas como 2 y versiones de Windows Server tan bajas como 2008 R2.[1]

Desde el servidor A, cree una sesión en el servidor B:

$b = New-PSSession B

Y luego, todavía de A:

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

La copia de elementos a B se hace con -ToSession. Tenga en cuenta que las rutas locales se utilizan en ambos casos; tienes que realizar un seguimiento del servidor en el que estás.


[1]: al copiar desde o hacia un servidor remoto que solo tiene PowerShell 2, tenga cuidado con este error en PowerShell 5.1 , que en el momento de escribir esto significa que la copia recursiva de archivos no funciona -ToSession, una copia aparentemente no funciona en todo con -FromSession.

Jeroen Mostert
fuente
3
He descubierto que no es necesario que ambos servidores tengan instalado PS 5. Acabo de realizar una prueba con éxito en la que solo el servidor de origen (Windows 10) tenía instalado PS 5. El objetivo era Windows Server 2012 R2 con PS predeterminado instalado ($ PSVersionTable.PSVersion informa 4).
Taylor Buchanan
2
Si usa -ToSession en la fuente, solo la fuente necesita instalar PS 5. Si usa -FromSession en el objetivo, solo el objetivo necesita instalar PS 5.
Taylor Buchanan
1
Esto también funciona cuando solo tiene instalado Hypervisor (sin servidor), no es necesario configurar recursos compartidos, ¡solo use las sesiones!
Dashesy
¡Gracias! Niza, solución elegante, similar a scplo largo sshde Linux ... no hay necesidad de molestarse con acciones molestos!
Tobias J
40

Utilice net useo New-PSDrivepara crear una nueva unidad:

New-PsDrive: cree un nuevo PsDrive solo visible en el entorno de PowerShell:

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

Uso neto: cree una nueva unidad visible en todas las partes del sistema operativo.

Net use y: \\ServerName\Share
Copy-Item BigFile Y:\BigFileCopy
JPBlanc
fuente
Si ejecuto esto dos veces, obtengo New-PSDrive : A specified logon session does not exist. It may already have been terminated-> Creo que una sesión anterior todavía está en curso -> Así que intenté usar Remove-PSDrive-> todavía no funciona. Tampoco net use <driveLetter> /deleteayudó. ¿Alguna otra cosa que pueda hacer para poder ejecutar este comando en una configuración de compilación de software?
Bruno Bieri
No tiene sentido ejecutar New-PSDrivedos veces que debería haberlo hechoA drive with the name 'Y' already exists.
JPBlanc
Estoy de acuerdo en que no tiene sentido ejecutarlo dos veces. Pero está incorporado en un paso de compilación y la compilación se ejecuta varias veces al día. Entonces, mi enfoque fue eliminar la unidad una vez que hice el trabajo que necesitaba y asumí que no sería un problema volver a crearla una vez que ocurra una nueva ejecución de compilación. Pero parece un problema. ¿Alguna otra pista?
Bruno Bieri
¿Qué hay de probar si está montado antes de montarlo? o puede usar Remove-PSDrive en su secuencia de comandos cuando esté seguro de que todos los identificadores que usan esta ruta están cerrados.
JPBlanc
16

En caso de que el archivo remoto necesite su credencial para acceder, puede generar un objeto System.Net.WebClient usando el cmdlet New-Object para "Copiar archivo de forma remota", así

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

O si necesita cargar un archivo, puede usar UploadFile:

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

$WebClient.UploadFile($Dest, $Source)
shyan1
fuente
1
@klm_ ¿Puedes explicar lo que quieres decir?
FastTrack
0

Ninguna de las respuestas anteriores funcionó para mí. Seguí recibiendo este error:

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

Entonces esto lo hizo por mí:

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

Luego, desde mi host, mi máquina en el cuadro Ejecutar, acabo de hacer esto:

\\{IP address of nanoserver}\C$
RogerW
fuente
1
Es probable que haya tenido problemas con los permisos de sistema de archivos + compartir. Recuerde que los permisos más restrictivos ganan, por lo que incluso si tiene acceso a la capa del sistema de archivos NTFS, si los permisos para compartir lo restringen, no podrá escribir. :)
Trevor Sullivan