peshkova - stock.adobe.com

Daten mit dem PowerShell FTP-Skript hoch- und herunterladen

Mit der .NET WebClient-Klasse und PowerShell laden Windows-Administratoren Dateien auf FTP hoch und runter. Wir erklären den Prozess anhand praktischer Beispiele.

Das Übertragen von Dateien per FTP (File Transfer Protocol) gehört zu den Aufgaben, die jeder Systemadministrator mindestens einmal in seiner Laufbahn erledigt hat. FTP und seine sicheren Komponenten gibt es schon seit langem. Es kopiert Dateien von einem Ort zu einem anderen, entweder in einem lokalen Netzwerk oder über das Internet.

PowerShell ist eine allgemeine, universelle Skriptsprache, mit der sich viele Aufgaben von Systemadministratoren automatisieren lassen, die scheinbar nichts miteinander zu tun haben.

Aber was passiert, wenn man sie zusammenbringt? Sie erhalten ein Rezept für ein leistungsstarkes und kostenloses Automatisierungs-Tool, das auf einer allgegenwärtigen Skriptplattform basiert. Administratoren können mit PowerShell und den .NET-Klassen leistungsstarke FTP-Skripte erstellen.

Lesen Sie weiter, um zu erfahren, wie Sie die Leistung von PowerShell mit FTP kombinieren, um PowerShell-Skripte zum Übertragen von Dateien von IP-Adresse zu IP-Adresse, Quellstammordner zu Zielserver und mehr zu erstellen.

Erstellen eines einfachen FTP-Skripts

Beginnen wir mit einem einfachen PowerShell-FTP-Skript, das eine einzelne Datei von einem System auf ein anderes überträgt und zur Authentifizierung einen Benutzernamen und ein Kennwort verwendet. Wir werden das Skript zunächst in Teilen erstellen, die wir am Ende zu einem vollständigen Skript zusammensetzen. Sie finden es nach den Einzelschritten im Artikel.

1. Erstellen des Skripts

Öffnen Sie Ihren bevorzugten PowerShell-Skripteditor und speichern Sie ein PS1-Skript mit dem Namen Upload-File.ps1. Dieses Skript enthält den gesamten Code, den Sie zum Hochladen einer Datei über FTP benötigen.

Erstellen Sie einige Parameter für das Skript. Da es sich bei PowerShell-Skripten um Tools handelt, ist es wichtig, dass Sie dieses Skript für andere Situationen wiederverwenden werden. Im Folgenden sehen Sie drei Parameter, mit denen Sie den Benutzernamen und das Kennwort – über ein PSCredential-Objekt – den lokalen Dateipfad und den Hostnamen des FTP-Servers übergeben.

[CmdletBinding()]

 param(

     [Parameter(Mandatory)]

     [pscredential]$Credential,

     [Parameter(Mandatory)]

     [string]$FilePath,

     [Parameter(Mandatory)]

     [string]$FtpServerHost

 )

Erstellen Sie ein .NET WebClient-Objekt. Dieses Objekt verfügt über Methoden zum Aufrufen von FTP-Übertragungen, unterstützt aber auch HTTP. Nach der Definition müssen Sie den Benutzernamen und das Kennwort in der Eigenschaft Credentials angeben, wie unten gezeigt.

$webclient = New-Object System.Net.WebClient

 $ftpPassword = $Credential.GetNetworkCredential().Password

 $webclient.Credentials = New-Object System.Net.NetworkCredential($Credential.Username, $ftpPassword)

Nachdem Sie das WebClient-Objekt erstellt und die Anmeldeinformationen definiert haben, müssen Sie festlegen, wo Sie die Datei speichern möchten. Zu diesem Zweck müssen Sie ein System.Uri .NET-Objekt erstellen, wie unten gezeigt.

$remoteFileName = $FilePath | Split-Path -Leaf

 $uri = New-Object System.Uri("ftp://$FtpServerHost/$remoteFileName")

Rufen Sie schließlich die Methode UploadFile() auf und verwenden Sie den kürzlich erstellten URI und den über das Skript erhaltenen Pfad. Mit dem folgenden Code wird die lokale Datei in das Stammverzeichnis des FTP-Servers hochgeladen.

$webclient.UploadFile($uri, $FilePath)

Das vollständige Skript sollte wie folgt aussehen.

[CmdletBinding()]

 param(

     [Parameter(Mandatory)]

     [pscredential]$Credential,

     [Parameter(Mandatory)]

     [string]$FilePath,

     [Parameter(Mandatory)]

     [string]$FtpServerHost

 )

 $webclient = New-Object System.Net.WebClient

 $ftpPassword = $Credential.GetNetworkCredential().Password

 $webclient.Credentials = New-Object System.Net.NetworkCredential($Credential.Username, $ftpPassword)

 $remoteFileName = $FilePath | Split-Path -Leaf

 $uri = New-Object System.Uri("ftp://$FtpServerHost/$remoteFileName")

 $webclient.UploadFile($uri, $FilePath)

 $webclient.Dispose()

2. Ausführen des Skripts

Um das Skript auszuführen, rufen Sie es wie im folgenden Befehl gezeigt auf. Der Befehl fordert Sie zur Eingabe eines Benutzernamens und eines Passworts auf. Mit diesem Benutzernamen und Kennwort authentifiziert sich das Skript dann beim FTP-Server ftpserver.domainname.com und überträgt die Datei C:.txt in das Stammverzeichnis des FTP-Servers.

.\Upload-File.ps1 -Credential (Get-Credential) -FilePath 'C:\Demo\file.txt' -FtpServerHost 'ftpserver.domainname.com'

Erstellen eines erweiterten FTP-Skripts

Lassen Sie uns nun dieses einfache Skript weiter ausbauen. Angenommen, Sie möchten eine Datei mit FTPS kopieren, um die Übertragung über das Netzwerk zu verschlüsseln. Dazu müssen Sie ein .NET WebRequest-Objekt verwenden.

Mit einer ähnlichen Technik können Sie das Skript Upload-Script.ps1 durch den unten stehenden Code ersetzen. Das Skript dient demselben Zweck und überträgt Dateien unverschlüsselt, bietet jetzt aber auch die Möglichkeit, Dateien sicher zu übertragen.

[CmdletBinding()]

 param(

     [Parameter(Mandatory)]

     [pscredential]$Credential,

     [Parameter(Mandatory)]

     [string]$FilePath,

     [Parameter(Mandatory)]

     [string]$FtpServerHost,

     [Parameter()]

     [switch]$SecureTransfer

 )

 ## Definieren Sie den FTP URI und die Anmeldedaten für die Verbindung.

 $ftpPassword = $Credential.GetNetworkCredential().Password

 $remoteFileName = $FilePath | Split-Path -Leaf

 $request = [Net.WebRequest]::Create("ftp://$FtpServerHost/$remoteFileName")

 $request.Credentials = New-Object System.Net.NetworkCredential($Credential.Username, $ftpPassword)

 ## Nur wenn Sie den $SecureTransfer-Switch-Parameter verwenden, übertragen Sie Daten mit FTPS.

 if ($SecureTransfer.IsPresent) {

     $request.EnableSsl = $true

 }

 ## Geben Sie das Request-Objekt an, das wir in die Datei übertragen werden.

 $request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile

 ## Öffnen Sie die Datei vor Ort, um geben Sie es an einen Request Stream weiter, für die Übertragung.

 $fileStream = [System.IO.File]::OpenRead($FilePath)

 $ftpStream = $request.GetRequestStream()

 ## Übertragen Sie die Datei

 $fileStream.CopyTo($ftpStream)

 ## Bereinigen Sie das Memory des .NET-Objekts.

 $ftpStream.Dispose()

 $fileStream.Dispose()

Hochladen oder Herunterladen eines ganzen Ordners

In Anlehnung an das obige erweiterte Skript müssen Sie vielleicht eine Datei herunterladen. Und was ist, wenn Sie nicht nur eine einzelne Datei, sondern alle Dateien eines Ordners übertragen müssen? Nachfolgend finden Sie ein Skript, das genau das tut.

In den Kommentaren finden Sie weitere Informationen zu den einzelnen Zeilen.

[CmdletBinding()]

 param(

     [Parameter(Mandatory)]

     [pscredential]$Credential,

     [Parameter(Mandatory)]

     [string]$LocalPath,

     [Parameter(Mandatory)]

     [string]$FtpServerHost,

     [Parameter(Mandatory)]

     [ValidateSet('Download','Upload')]

     [string]$Direction

 )

 $webclient = New-Object System.Net.WebClient

 $ftpPassword = $Credential.GetNetworkCredential().Password

 $webclient.Credentials = New-Object System.Net.NetworkCredential($Credential.Username, $ftpPassword)

 if ($Direction -eq 'Download') {

     ## Finden Sie alle Dateien auf dem FTP-Server

     $request = [Net.WebRequest]::Create($url)

   $request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory

     $request.Credentials = $credentials

   $response = $request.GetResponse()

   $reader = New-Object IO.StreamReader $response.GetResponseStream()

     $files = while(-not $reader.EndOfStream) {

         $reader.ReadLine()

   }

   $reader.Close()

   $response.Close()

     ## Laden Sie die Dateien herunter.

     foreach ($file in $files){

         $source = "$uri/$file"

     $destination = "$LocalPath/$file"

     $webclient.DownloadFile($source, $destination)

   }

 } elseif ($Direction -eq 'Upload') {

     ## Finden Sie alle lokalen Dateien und Laden Sie sie hoch.

     Get-ChildItem -Path $LocalPath | ForEach-Object {

         $uri = New-Object System.Uri("ftp://$FtpServerHost/$($_.Name)")

         $webclient.UploadFile($uri, $_.FullName)

     }

 }

Überwachen des Fortschritts

Wenn Sie eine große Datei übertragen und wissen möchten, wie viele Daten übertragen wurden, gibt es eine einfache Möglichkeit, dies herauszufinden. Eine davon ist das Cmdlet Write-Progress. Dieses Cmdlet stellt einen grafischen Fortschrittsbalken bereit, der Ihnen anzeigt, wie weit die Übertragung fortgeschritten ist.

Es gibt verschiedene Möglichkeiten, den Fortschritt einer Dateiübertragung mit einem Fortschrittsbalken zu verfolgen. Eine der einfachsten Möglichkeiten besteht darin, die Datei nicht auf einmal, sondern in Teilen hochzuladen und mit dem Cmdlet Write-Progress einen fortlaufenden Fortschrittsbalken zu erzeugen, der darauf basiert, wie viele Teile übertragen wurden. Der folgende Code zeigt, wie Sie den Übertragungsfortschritt auf diese Weise verfolgen.

[CmdletBinding()]

 param(

     [Parameter(Mandatory)]

     [pscredential]$Credential,

     [Parameter(Mandatory)]

     [string]$LocalPath,

     [Parameter(Mandatory)]

     [string]$FtpServerHost

 )

 $remoteFileName = $FilePath | Split-Path -Leaf

 $request = [Net.WebRequest]::Create("ftp://$FtpServerHost/$remoteFileName")

 $ftpPassword = $Credential.GetNetworkCredential().Password

 $webclient.Credentials = New-Object System.Net.NetworkCredential($Credential.Username, $ftpPassword)

 $request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile

 $fileStream = [System.IO.File]::OpenRead($LocalFilePath)

 $ftpStream = $request.GetRequestStream()

 $buffer = New-Object Byte[] 10240

 while (($read = $fileStream.Read($buffer, 0, $buffer.Length)) -gt 0) {

     $ftpStream.Write($buffer, 0, $read)

     $pct = ($fileStream.Position / $fileStream.Length)

         $prgParams = @{

             'Activity' =  'Uploading'

             'Status' =  ("{0:P0} complete:" -f $pct)

       'PercentComplete' = ($pct * 100)

         }

     Write-Progress @prgParams

 }

 $fileStream.CopyTo($ftpStream)

 $ftpStream.Dispose()

 $fileStream.Dispose()

Wenn Sie ein Systemadministrator sind, verstehen Sie vielleicht nicht den ganzen fortgeschrittenen .NET-Code in diesem Artikel. Der Große Vorteil beim Erstellen von Skripten für Aufgaben wie diese ist jedoch, dass Sie das nicht müssen. Nutzen Sie den vorhandenen Code, der hier zur Verfügung gestellt wird, und beginnen Sie mit dem Ausführen der Skripte selbst, anstatt sich in den Code zu vertiefen.

Erfahren Sie mehr über Serverbetriebssysteme

ComputerWeekly.de
Close