olly - stock.adobe.com
Daten mit einem PowerShell FTP-Skript up- und downloaden
Mithilfe von PowerShell oder .NET WebClient-Klasse werden Daten auf FTP up- und downgeloadet. Wie genau es funktioniert, erfahren Sie hier anhand praktischer Beispiele.
Jeder Systemadministrator muss manchmal in seinem Leben Dateien per FTP (File Transfer Protocol) übertragen. FTP gibt es schon lange und der Kopiervorgang geht sicher entweder in einem lokalen Netzwerk oder über das Internet vonstatten.
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? Man erhält ein leistungsstarkes und kostenloses Automatisierungs-Tool, das auf einer überall verfügbaren Skriptplattform basiert. Administratoren können mit PowerShell und den .NET-Klassen leistungsstarke FTP-Skripte erstellen.
Im Folgenden erfahren Sie, 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.
Wie Sie ein einfaches FTP-Skript erstellen
Beginnen wir mit einem einfachen PowerShell-FTP-Skript, das eine einzelne Datei von einem Server 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. Skript-Erstellung
Ö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. Skript-Ausführung
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'
Wie Sie ein erweitertes FTP-Skript erstellen
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 untenstehenden 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 $Secure-Transfer-Switch-Parameter verwenden, übertragen Sie Daten mit FTPS.
if ($SecureTransfer.IsPresent) {
$request.EnableSsl = $true
}
Gegen Sie das Request-Objekt an, das wir in die Datei übertragen werden.
$request.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
Öffnen Sie die lokale Datei und konvertieren Sie in einen Request Stream zur Ü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()
Wie Sie einen ganzen Ordner hoch- oder herunterladen
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)
}
}
Wie Sie den Fortschritt überwachen
Wenn Sie eine große Datei übertragen und wissen möchten, wie viele Daten übertragen wurden, gibt es eine einfache Möglichkeit, das 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.