PowerShell : Copier des fichiers avec BITS
Sommaire
I. Présentation
BITS (Background Intelligent Transfer Service) est un composant de Windows qui permet d'effectuer des transferts de données intelligents en arrière-plan, il offre des possibilités intéressantes par rapport à une simple copie, notamment :
- La possibilité de mettre en pause et de reprendre un téléchargement (même en cas de coupure réseau) - Comme peut le permettre l'excellent Robocopy
- La possibilité de gérer la priorité c'est-à-dire la bande passante que l'on va allouer par rapport à l'activité réseau de la machine sur laquelle il s'exécute (paramètre "Priority" du commandlet "Start-BitsTransfer")
- Une véritable gestion des jobs, qui peuvent se dérouler en mode synchrone ou asynchrone
Ce n'est pas un nouveau composant intégré par Microsoft récemment puisqu'il existe depuis Windows XP mais il a évolué au fil des versions de Windows (via bitsadmin.exe), le module PowerShell quant à lui est présent depuis PowerShell 2.0.
BITS dispose de son propre module PowerShell nommé "BitsTransfer" et qui permet de gérer des jobs via la ligne de commande, ce qui est intéressant pour scripter, surtout pour transférer des gros fichiers où la probabilité qu'une coupure intervienne est plus forte.
Au-delà de PowerShell, BITS est utilisé notamment par WSUS, Windows Update ou encore Microsoft Virtual Machine Converter.
Dans ce tutoriel, nous allons voir ensemble comment télécharger des fichiers avec BITS via PowerShell, puis en fin d'article je vais vous orienter vers un script que j'ai publié sur GitHub et qui s'appuie sur BITS. L'objectif du script que je partage est de pouvoir télécharger toute une arborescence de données à partir d'un dossier racine (source), car BITS n'inclus pas nativement cette notion de récursivité. Il est capable de télécharger tous les fichiers situés dans un dossier, mais il n'ira pas voir dans les sous-dossiers.
II. Importer le module BitsTransfer
Si vous êtes familier avec PowerShell, l'importation d'un module doit être un jeu d'enfant pour vous, voici tout de même la commande qui permet d'importer le module BitsTransfer :
Import-Module BitsTransfer
Ensuite, on peut lister les commandes du module BitsTransfer :
Get-Command -Module BitsTransfer CommandType Name Version Source ----------- ---- ------- ------ Cmdlet Add-BitsFile 2.0.0.0 BitsTransfer Cmdlet Complete-BitsTransfer 2.0.0.0 BitsTransfer Cmdlet Get-BitsTransfer 2.0.0.0 BitsTransfer Cmdlet Remove-BitsTransfer 2.0.0.0 BitsTransfer Cmdlet Resume-BitsTransfer 2.0.0.0 BitsTransfer Cmdlet Set-BitsTransfer 2.0.0.0 BitsTransfer Cmdlet Start-BitsTransfer 2.0.0.0 BitsTransfer Cmdlet Suspend-BitsTransfer 2.0.0.0 BitsTransfer
À l'heure où j'écris ces lignes, le module BitsTransfer est en version 2.0 et il intègre 8 commandlets qui vont permettre de créer des jobs avec BITS et de les gérer. Dans ce tutoriel, nous n'utiliserons pas tous les commandlets mais seulement : Get-BitsTransfer, Complete-BitsTransfer, Start-BitsTransfer.
Note : Les commandlets "Suspend-BitsTransfer" et "Resume-BitsTransfer" permettent respectivement de suspendre un job BITS ou de reprendre un job BITS suspendu.
Pour obtenir de l'aide sur les différents commandlets du module : Help BitsTransfer
III. Télécharger un fichier avec BITS, via HTTP(S)
Passons maintenant à quelque chose de plus intéressant : le téléchargement d'un fichier par l'intermédiaire d'un job BITS. On s'appuiera sur le commandlet "Start-BitsTransfer" et deux paramètres : la source et la destination. C'est un strict minimum pour utiliser ce commandlet qui offre bien d'autres possibilités.
Pour télécharger un fichier à partir de l'URL "https://owncloud.mon-domaine.fr/index.php/s/xiiI7SmWQzsGV5G/download" et le stocker dans "C:\temp\" en lui donnant comme nom "mon-fichier.iso.gz" voici la commande à exécuter :
Start-BitsTransfer -Source "https://owncloud.mon-domaine.fr/index.php/s/xiiI7SmWQzsGV5G/download" -Destination "C:\temp\mon-fichier.iso.gz"
Une barre de progression s'affiche :
Lors d'un téléchargement, il y a différentes phases : Connecting, Transferring et Transferred (lorsque le téléchargement est terminé), on peut aussi rencontrer "TransientError" s'il y a un job en erreur. Par défaut, le mode de fonctionnement est synchrone ce qui implique qu'avant de continuer, le script attendra la fin du téléchargement. Pour lancer plusieurs jobs en boucle à la volée, il faudra passer en mode asynchrone, c'est ce que nous allons voir maintenant.
III. Téléchargement asynchrone avec BITS, via HTTP(S)
Le passage en mode asynchrone implique qu'il faut indiquer le paramètre "-Asynchronous" à la commande que l'on exécuter précédemment, ce qui donnera :
Start-BitsTransfer -Source "https://owncloud.mon-domaine.fr/index.php/s/xiiI7SmWQzsGV5G/download" -Destination "C:\temp\mon-fichier.iso.gz" -Asynchronous
Cette commande retourne :
JobId DisplayName TransferType JobState OwnerAccount ----- ----------- ------------ -------- ------------ 3a381ff9-2bff-4081-bbff-63eb17abf976 BITS Transfer Download Connecting FLOSTATION\Florian
Note : Vous remarquerez dans la sortie de commande ci-dessus, la valeur "TransferType" à "Download". Ceci est logique, car BITS permet aussi de réaliser des jobs d'upload, pour cela il faudra utiliser le paramètre "TransferType" avec Start-BitsTransfer".
On peut voir l'évolution de notre job BITS en invoquant régulièrement "Get-BitsTransfer" :
Lorsque l'on est en mode asynchrone, il faut valider la fin du job BITS pour que le fichier soit sauvegardé sur votre machine à l'endroit indiqué dans le paramètre "Destination". Pour valider tous les jobs, on utilise la commande suivante :
Get-BitsTransfer | Complete-BitsTransfer
On aurait pu aussi préciser uniquement le job que l'on vient de lancer, soit par le JobId ou son DisplayName, ce qui donnerait :
Get-BitsTransfer -JobId "3a381ff9-2bff-4081-bbff-63eb17abf976" | Complete-BitsTransfer
À partir de ce moment-là (sauf s'il y a eu une erreur), le fichier est enregistré sur votre machine.
Passons maintenant au dernier exemple de ce tutoriel...
IV. Télécharger un ensemble de fichiers avec BITS, via SMB
Le téléchargement de fichiers avec BITS ne s'arrête pas au lien web, je dirais même qu'il sera surement plus utilisé avec des transferts de fichiers via des liens SMB pour accéder à des partages.
De manière générale, la commande Start-BitsTransfer s'utilise pareil. Par exemple, pour télécharger tous les fichiers d'un dossier à partir d'un chemin UNC :
Start-BitsTransfer -Source "\\192.168.1.150\Download\BITS\*.*" -Destination "C:\temp\"
Dans la destination, les fichiers vont conserver leurs noms d'origine. Mais alors, vous allez me dire comment on fait pour s'authentifier sur un partage où c'est nécessaire ? Microsoft a prévu le coup en intégrant au commandlet Start-BitsTransfer un paramètre "Credential" qui peut recevoir un objet de type PSCredential avec un couple login/password pour s'authentifier.
Ce qui donne (par exemple) :
$MyCred = Get-Credential
Start-BitsTransfer -Source "\\192.168.1.150\Download\BITS\*.*" -Destination "C:\temp\" -Credential $MyCred
J'en ai fini des démonstrations liées à BITS, n'hésitez pas à explorer ses différents paramètres et commandlets, notamment la gestion de la priorité pour un job, la gestion des credentials, la possibilité de passer outre un proxy, etc...
Pour ceux que ça intéresse, voici le script que j'ai publié sur GitHub : Start-BitsDownloadRecursive
-> Si vous mettez en source une arborescence avec un dossier racine, contenant des fichiers, puis des sous-dossiers avec d'autres fichiers, ces sous-dossiers peuvent contenir d'autres dossiers avec eux aussi des fichiers, etc... Tout sera recréé au sein de la destination avec la même arborescence et les mêmes noms de fichiers, en s'appuyant sur BITS. Un job BITS par sous-dossier sera généré :
D'ailleurs ce script peut-être amélioré (voire optimisé) et des fonctions ajoutées, alors n'hésitez pas à donner votre avis 🙂