Copier le fichier à distance avec PowerShell

94

J'écris un script PowerShell que je souhaite exécuter à partir du serveur A. Je souhaite me connecter au serveur B et copier un fichier sur le serveur A en tant que sauvegarde.

Si cela ne peut pas être fait, je voudrais me connecter au serveur B à partir du serveur A et copier un fichier dans un autre répertoire du serveur B.

Je vois la Copy-Itemcommande, mais je ne vois pas comment lui donner un nom d'ordinateur.

J'aurais pensé que je pourrais faire quelque chose comme

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

Comment puis-je faire ceci?

chobo2
la source
4
Pour utiliser Copy-Item, vous devrez utiliser un chemin UNC comme "\\ ServerB \ C $ \ Programs \ temp \ test.txt"

Réponses:

96

Utilisez simplement les partages administratifs pour copier des fichiers entre les systèmes. C'est beaucoup plus facile de cette façon.

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

En utilisant des chemins UNC au lieu des chemins du système de fichiers local, vous vous assurez que votre script est exécutable à partir de n'importe quel système client ayant accès à ces chemins UNC. Si vous utilisez des chemins de système de fichiers locaux, vous vous efforcez d'exécuter le script sur un ordinateur spécifique.

Cela ne fonctionne que lorsqu'une session PowerShell s'exécute sous l'utilisateur qui a des droits sur les deux partages administratifs.

Je suggère d'utiliser le partage réseau régulier sur le serveur B avec un accès en lecture seule à tout le monde et d'appeler simplement (à partir du serveur A):

Copy-Item -Path "\\\ServerB\SharedPathToSourceFile" -Destination "$Env:USERPROFILE" -Force -PassThru -Verbose
Trevor Sullivan
la source
9
Un problème possible avec cette approche est que Copy-Item ne prend pas en charge d'autres informations d'identification (si vous devez exécuter la commande avec un utilisateur différent). Dans ce cas, l'approche New-PSDrive est requise.
Jordanie
1
Cette solution ne fonctionne que s'il n'y a pas de pare-feu entre les hôtes bloquant les partages UNC. Dans ce cas, la solution correcte est ci-dessous ( Copy-Item -FromSession).
Marc
85

À partir de PowerShell version 5 (inclus dans Windows Server 2016, téléchargeable dans le cadre de WMF 5 pour les versions antérieures ), cela est possible avec l'accès à distance. L'avantage est que cela fonctionne même si, pour une raison quelconque, vous ne pouvez pas accéder aux partages.

Pour que cela fonctionne, la session locale où la copie est lancée doit avoir PowerShell 5 ou une version ultérieure installée. La session à distance n'a pas besoin d'installer PowerShell 5 - elle fonctionne avec les versions PowerShell aussi basses que 2 et les versions Windows Server aussi basses que 2008 R2. [1]

À partir du serveur A, créez une session sur le serveur B:

$b = New-PSSession B

Et puis, toujours de A:

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

La copie des éléments vers B se fait avec -ToSession. Notez que les chemins locaux sont utilisés dans les deux cas; vous devez garder une trace de quel serveur vous êtes.


[1]: lors de la copie depuis ou vers un serveur distant qui n'a que PowerShell 2, méfiez-vous de ce bogue dans PowerShell 5.1 , qui au moment de l'écriture signifie que la copie de fichiers récursive ne fonctionne pas avec -ToSession, une copie apparemment ne fonctionne pas à tout avec -FromSession.

Jeroen Mostert
la source
3
J'ai trouvé qu'il n'était pas nécessaire que les deux serveurs aient installé PS 5. Je viens d'effectuer un test réussi où seul le serveur source (Windows 10) avait installé PS 5. La cible était Windows Server 2012 R2 avec PS par défaut installé (rapports $ PSVersionTable.PSVersion 4).
Taylor Buchanan
2
Si vous utilisez -ToSession sur la source, seule la source nécessite l'installation de PS 5. Si vous utilisez -FromSession sur la cible, seule la cible nécessite l'installation de PS 5.
Taylor Buchanan
1
Cela fonctionne également lorsque vous n'avez installé que Hypervisor (sans serveur), pas besoin de configurer des partages, utilisez simplement les sessions!
dashesy
Je vous remercie! Belle solution élégante, similaire à scpover sshsur Linux ... pas besoin de s'embêter avec des partages embêtants!
Tobias J
40

Utilisez net useou New-PSDrivepour créer un nouveau lecteur:

New-PsDrive: créez un nouveau PsDrive visible uniquement dans l'environnement PowerShell:

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

Net use: créez un nouveau lecteur visible dans toutes les parties du système d'exploitation.

Net use y: \\ServerName\Share
Copy-Item BigFile Y:\BigFileCopy
JPBlanc
la source
Si je l'exécute deux fois, j'obtiens New-PSDrive : A specified logon session does not exist. It may already have been terminated-> Je pense qu'une session précédente est toujours en cours -> J'ai donc essayé d'utiliser Remove-PSDrive-> cela ne fonctionne toujours pas. Aussi net use <driveLetter> /deleten'a pas aidé. Est-ce que je peux faire autre chose pour pouvoir exécuter cette commande dans une configuration de build logiciel?
Bruno Bieri
Cela n'a aucun sens de courir New-PSDrivedeux fois que vous auriez dûA drive with the name 'Y' already exists.
JPBlanc
Je conviens que cela n'a aucun sens de l'exécuter deux fois. Mais il est incorporé dans une étape de construction et la construction s'exécute plusieurs fois par jour. Donc, mon approche était de supprimer le lecteur une fois que j'avais fait le travail dont j'avais besoin et je supposais que ce ne serait pas un problème de le recréer une fois qu'une nouvelle exécution de construction se produirait. Mais cela semble un problème. Un autre indice?
Bruno Bieri
Qu'en est-il de tester s'il est monté avant de le monter? ou vous pouvez utiliser Remove-PSDrive dans votre script lorsque vous êtes sûr que tous les descripteurs utilisant ce chemin sont fermés.
JPBlanc
16

Juste au cas où le fichier distant a besoin de vos informations d'identification pour y accéder, vous pouvez générer un objet System.Net.WebClient à l' aide de l'applet de commande New-Object pour "Copier le fichier à distance", comme ceci

$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 si vous avez besoin de télécharger un fichier, vous pouvez utiliser UploadFile:

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

$WebClient.UploadFile($Dest, $Source)
shyan1
la source
1
@klm_ Pouvez-vous expliquer ce que vous voulez dire?
FastTrack
0

Aucune des réponses ci-dessus n'a fonctionné pour moi. J'ai continué à recevoir cette erreur:

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

Alors ça l'a fait pour moi:

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

Ensuite, depuis mon hôte, ma machine dans la boîte Exécuter, je viens de faire ceci:

\\{IP address of nanoserver}\C$
RogerW
la source
1
Il y a de fortes chances que vous ayez rencontré des problèmes avec les autorisations de partage + système de fichiers. N'oubliez pas que les autorisations les plus restrictives l'emportent, donc même si vous avez accès à la couche du système de fichiers NTFS, si les autorisations de partage vous restreignent, vous ne pourrez pas écrire. :)
Trevor Sullivan