PowerShell – работаем с FTP сервером


Метод 1. Одна из полезных и удобных особенностей PowerShell – возможность прозрачно взаимодействовать с утилитами командной строки.

В Windows досточно много утилит командной строки, которые уже много лет служат верой и правдой. Многие  утилиты хорошо известны и широко используются. Некоторые решают свою задачу быстро и эффективно. Cовершенно неоправдано ожидать, что PowerShell заменит их сразу и полностью. В ряде случаев такая замена вообще неоправдана. Хорошо, что PowerShell не требует от нас переписывать существующие утилиты на .NET Framework и позволяет использовать всю их мощь.

Одна из таких утилит ftp.exe Утилита специфическая и по современным понятиям неудобная. Но она стандартная и администратор может ее использовать при необходимости на любой системе без лишних усилий. Чтобы несколько уменьшить неуклюжесть интерфейса утилиты ftp.exe , используем PowerShell.

Конечно мы не будем делать универсальную обертку: просто продемонстрируем технику и за одно решим вполне практическую задачу копирования списка файлов с ftp-сервера: сделать это стандартными командами вручную непросто (написать 5 команд get еще можно, а 15 уже утомительно).

Для начала создадим список команд в переменной (каждая команда пишется на новой строке!):

>$FileList = "open 17.17.17.21

user USERNAME PASSWORD

binary

cd DIRECTORYNAME

mdir * -" | ftp -i -n | where {$_.Trim() -ne "" } 

 

В результате получим листинг нужной директории. Обратите внимание, что использована команда “mdir * — “ – звездочка, пробел, минус. Далее убраны пустые строки. Для конкретного ftp-сервера возможно придется убрать иной мусор.

 Получив список файлов, мы можем использовать PowerShell для его предварительной обработки и фильтрации, чтобы выбрать нужные нам файлы для последующего копирования, например за определенную дату:

>$FileList = $FileList | Where {-not $_.StartsWith("d")} | Where {$_.Contains("Dec 22  2005")} | %{ $_.SubString(49) }

 

Тут сначала убраны директории, затем выбраны файлы за определенную дату, а потом  вырезаны имена файлов.

Теперь скопируем эти файлы на локальную машину:

>$cmd = " open 17.17.17.21

user USERNAME PASSWORD

binary

cd DIRECTORYNAME

" +

($FileList | %{ "get ""$_""`n" })

$cmd | ftp -i –n

 

Как видите утилита ftp принимает команды через стандартный поток ввода и выдает результат на стандартный поток вывода. Эта ее особенность использована в приведенном примере.

Примечание.Некоторые утилиты не могут принимать команды через стандартный поток, но могут принимать команды из файла. В этом случае нам придется создать вспомогательный файл команд. Аналогичная ситуация может возникнуть с выводом результатов в файл.

Конечно приведенную технику можно использовать не только для загрузки файлов, но и для выгрузки на сервер: достаточно изменить команду get на команду put.

 

Метод 2. Другой метод работы с FTP сервером – использовать средства  .NET Framework.

Получить список файлов (DIR):

>$server = "17.17.17.21"

>$filename = "DIRECTORY"

>$url = ftp://$server/$filename

>[System.Net.FtpWebRequest]$WR = [System.Net.WebRequest]::Create($url)

>$WR.Method = [System.Net.WebRequestMethods+FTP]::ListDirectoryDetails

>$WR.Proxy = $null

>$WR.Credentials = New-Object System.Net.NetworkCredential("USERNAME", "PASSWORD")

>$WRStream = $WR.GetResponse();

>$responseStream = $WRStream.GetResponseStream()

>$readStream = new-object System.IO.StreamReader($responseStream, [System.Text.Encoding]::UTF8)

>$FileList =$readStream.ReadToEnd()

>$FileList = $FileList.Split("`n`r")

 

Примечание. Получить список методов для запросов:

>[System.Net.WebRequestMethods+FTP].GetMembers() | ft Name

 

Отфильтровать список файлов и получить только нужные файлы:

> $FileList = $FileList | Where {-not $_.StartsWith("d")} | Where {$_.Contains("Dec 22  2005")} | %{ $_.SubString(49) }

 

Загрузить файлы по сформированному списку:

>$FileList | % {

[System.Net.FtpWebRequest]$WR = [System.Net.WebRequest]::Create($url+"/$_")

$WR.Method = [System.Net.WebRequestMethods+FTP]::DownloadFile

$WR.Proxy = $null

$WR.UseBinary = $True

$WR.Credentials = New-Object System.Net.NetworkCredential("USERNAME", "PASSWORD")

$WRStream = $WR.GetResponse()

$responseStream = $WRStream.GetResponseStream()

$readStream = new-object System.IO.StreamReader($responseStream, [System.Text.Encoding]::UTF8)

$a=$readStream.ReadToEnd()

Out-File -FilePath $_ -inputobject $a }

 

Обратная задача – выгрузка файлов по списку на сервер (не тестировано):

>$FileList | % {

[System.Net.FtpWebRequest]$WR = [System.Net.WebRequest]::Create($url+"/$_")

$WR.Method = [System.Net.WebRequestMethods+FTP]::UploadFile

$WR.Proxy = $null

$WR.UseBinary = $True

$WR.Credentials = New-Object System.Net.NetworkCredential("USERNAME", "PASSWORD")

$WRStream = $WR.GetResponse()

$responseStream = $WRStream.GetResponseStream()

$WriteStream = new-object System.IO.StreamWriter($responseStream, [System.Text.Encoding]::UTF8)

Get-Content $_ | % {$WriteStream.WriteString($_)

$WriteStream.Close()

$responseStream.Close()

$WRStream.Close()}

 

Загрузку одиночного файла можно выполнить более экономным методом. Для этого можно применить класс  WebClient Class:

>$WC = new-object System.Net.WebClient

>$server = "17.17.17.21"

>$filename = "DIRECTORY/FILENAME"

>$url = "ftp://$server/$filename"

>$WC.Proxy = $null

>$Wc.Credentials = New-Object System.Net.NetworkCredential("USERNAME", "PASSWORD")

>$localfile = "LOCALFILENAME"

>$WC.DownloadFile($url,$localfile)

 

Для выгрузки файла на сервер надо поменять последнюю строку:

>$WC. UploadFile($url,$localfile)

 

Метод 3.  Загрузить и установить какое-нибудь дополнение к PowerShell для работы с сетью. Есть коммерческие варианты. Есть бесплатные (Indy). Примеры смотрите в самих пакетах.

 

Заключение. Как видите, написание кода несколько более объемная задача, чем использование утилиты с хорошо продуманным интерфейсам. Впрочем это верно и для командлетов. Вывод напрашивается сам собой: PowerShell позволяет нам использовать всю мощь .NET Framework, но иногда мощь языка программирования нам лишняя: если есть удобная утилита, то в большинстве случаев ее можно использовать в PowerShell легко, просто и удобно получая компактный и быстрый скрипт для решения задачи.

 

 

Источники:

1.       http://feelingsofwhite.com/2007/03/look-what-you-can-do-in-powershell-ftp/

2.       WebRequest Class

3.       FtpWebResponse Class

4.       WebRequestMethods.Ftp Class (как работать с вложенными классами  http://blogs.msdn.com/powershell/archive/2009/08/27/plus-in-net-class-names.aspx )

5.       WebClient Class

 

 

 

комментария 2

  1. А как можно удалить файл к которому лезем по FTP/

    • Вызов метода удаления файла в контексте статьи $WR.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile

Оставьте комментарий