Powershell - FTP Module
I’ve been learning Windows Powershell over the past year, and developing scripts for scheduled tasks to perform administrative functions. One of the tasks requires data retrieval from an FTP server, waits for the data to be processed, and then puts the results back to the FTP server.
Lots of FTP functions have been written and are freely available, but I’ve found Michal Gajda’s PSFTP client module the easiest and most efficient method. It has functions to set multiple connections, and list, get, put, and remove files and folders.
Import-Module
The PSFTP module is not native to Powershell. To use the module, download and install, then import to access it’s functions and perform FTP processes.
- Download from http://gallery.technet.microsoft.com/scriptcenter/PowerShell-FTP-Client-db6fe0cb
- Extract the module to your PS Module folder (found at $env:PSModulePath)
- Import-Module using
Import-Module PSFTP
Local Variables
Now for the administrative task I was working on. Some local variables are declared for use throughout the script:
$ftp_server = "ftp://example.server.com"
$ftp_path = "$ftp_server/folder1/subfolder2"
$local = "\\localserver\sharedfolder1\subfolder2\"
$local_in = Join-Path $local "In"
$local_out = Join-Path $local "Out"
$session = "my_ftp_session"
Credentials
The connection credentials should not be stored in clear-text, but loaded from a SecureString file (which has been created using the appropriate account on the appropriate server). To establish the credentials:
# set up credentials object
$username = "username"
$password = Get-Content "pscredentials_$username.txt" |
ConvertTo-SecureString
$cred = New-Object `
-TypeName System.Management.Automation.PSCredential `
-ArgumentList $username, $password
Get Items
To input the files from FTP to local folder:
# establish connection
# get *.REQ files
# copy *.REQ files to local In folder
# remove *.REQ files from FTP server
Set-FTPConnection -Server $ftp_server -Credentials $cred `
-Session $session -KeepAlive -UseBinary
Get-FTPChildItem -Path $ftp_path -Filter *.REQ -Session $session |
% {
$ftp_file = "$ftp_path/$($_.Name)" # determine item fullname
Get-FTPItem -Path $ftp_file -LocalPath $local_in `
-Session $session -Overwrite
Remove-FTPItem -Path $ftp_file -Session $session
}
Put Items
After the data arrives at the local In folder it is processed by a separate application, which returns output to the local Out folder. It can then be put to the FTP server with:
# get all files in local Out folder
# put all files to FTP server
Get-ChildItem -Path $local_out |
% {
$ftp_file = "$ftp_path/$($_.Name)" # determine item fullname
Add-FTPItem -Path $ftp_file -LocalPath $_.FullName -Session $session
}
Notes
- The Get and Put actions have been performed within foreach loops ( % {} ) for logging purposes, such that action results are recorded to a text file for later reference. It would be more efficient to pipe the ChildItem results directly, but logging is important for historical tracing and action confirmation.
- The code lines could be shorter with the use of aliases, for example, by replacing Get-ChildItem with ls, and Copy-Item with cp. I don’t use aliases (except foreach loops) for a couple of reasons:
- using aliases doesn’t make code production faster (due to Tab completion)
- using full commands makes code more readable
Powershell is a great tool for Windows administration. I hope to continue learning thanks to the Scripting Guy, and shared script resources. How have you used Powershell?