- Копирование больших файлов по сети с помощью BITS и PowerShell
- Протокол BITS
- BITS: требования к ОС и версии PowerShell
- Как скачать файл по протоколу BITS с помощью PowerShell
- Синхронная передача файлов между компьютерами с помощью BITS
- Используем BITS для асинхронного копирования больших файлов по сети
- Копирование всего содержимого общей сетевой папки через BITS
- Загрузка файла на HTTP сервер с помощью PowerShell и BITS
- Copy-Item копирование файлов и папок из PowerShell
- Копирование файлов и каталогов
- Копирование с заменой и копирование с заменой read-only файлов
- Копирование с фильтрацией по шаблону
- Исключение файлов при копировании
- Копирование файлов на удаленный компьютер по сети
- Ключ PassThru
- Ключ Verbose
- Несколько полезных скриптов с Copy-Item
Копирование больших файлов по сети с помощью BITS и PowerShell
В локальных (да и глобальных) сетях файлы между системами обычно передаются с помощью протоколов SMB, FTP или HTTP. Проблема всех этих протоколов – сложности с докачкой больших файлов, которые могут усугубляться проблемами передачи данных по медленному или нестабильному каналу. При копировании файлов по этим протоколам обычно задействуется вся доступная пропускная способность канала связи между сервером и получателем, что может негативно сказаться на производительности сети и работе других приложения (не всегда возможно настроить корректные политики QoS на уровне сетевого оборудования). В этой статье мы рассмотрим возможность использования протокола BITS и командлетов PowerShell для копирования больших файлов через сеть по нестабильному или медленному каналу.
Протокол BITS
BITS или Background Intelligent Transfer service — (Фоновая интеллектуальная служба передачи) – это служба Windows, которая используется для передачи файлов между системами. С помощью протокола BITS можно передавать как скачивать, так и закачивать файлы. Именно по этому протоколу компьютеры скачивают файлы с серверов при выполнении автоматического обновлении Windows (в т.ч. при скачивании обновлений со WSUS сервера), при получении программ с SCCM точек распространения и т.д.
Преимущества протокола BITS:
- BITS — интеллектуальный протокол, который при работе способен регулировать используемую полосу канала связи, чтобы не оказывать влияния на другие сетевые приложения и сервисы. BITS может использовать только незанятую полосу пропускания канала и динамически изменять скорость передачи данных в процессе работы (если другие приложения увеличат нагрузку на сеть, BITS может уменьшить скорость передачи данных по сети);
- Загрузка файла может идти в фоновом режиме, незаметно для пользователя;
- Задание BITS в режиме докачки будет автоматически продолжено даже в случае обрыва канали связи между компьютером и клиентом, или после перезагрузки компьютера;
- В любой момент вы можете приостановить или возобновить загрузку по BITS без потери данных;
Таким образом, BITS является оптимальным протоколом для передачи больших файлов по медленным и нестабильным сетям (спутниковый канал, GPRS соединение и т.д.).
BITS: требования к ОС и версии PowerShell
Протокол BITS впервые был представлен еще в Windows XP, для управления заданиями BITS в которой можно было использовать утилиту bitsadmin.exe. Утилита все еще поддерживается, однако считается устаревшей. Для управления заданиями BITS предпочтительно использовать специальные командлеты PowerShell.
Для работы по рассматриваемому сценарию нам потребуется ОС не ниже Windows Vista или Windows Server 2008, и PowerShell не ниже версии 2.0. Современные версии Windows 10 и Windows Server 2016 / 2012 R2 протокол BITS полностью поддерживают.
Поддержка BITS требуется как на стороне клиента, так и сервера.
Как скачать файл по протоколу BITS с помощью PowerShell
Предположим вы хотите скачать большой ISO файл, хранящийся на HTTP сервере IIS ( _http://10.2.2.148/erd65_32.iso ).
Предполагается, что к данному URL адресу разрешен анонимный доступ (в дальнейшем мы рассмотрим доступ к URL адресу с аутентификацией).
В первую очередь загрузите в сессию PowerShell модуль поддержки BITS:
После загрузки модуля, вы можете вывести список всех доступных команд модуля BitsTransfer:
Как вы видите, доступно всего 8 командлетов:
- Add-BitsFile
- Complete-BitsTransfer
- Get-BitsTransfer
- Remove-BitsTransfer
- Resume-BitsTransfer
- Set-BitsTransfer
- Start-BitsTransfer
- Suspend-BitsTransfer
Синхронная передача файлов между компьютерами с помощью BITS
Командлет Start-BitsTransfer позволяет скачивать файлы по HTTP(s) (как и комадндет Invoke-WebRequest), так и из общих сетевых папок (по SMB). Чтобы скачать файл с указанного URL адреса по протоколу BITS и сохранить его в локальный каталог C:\Temp, воспользуйтесь командой:
Start-BitsTransfer –source _http://10.2.2.148/erd65_32.iso -destination c:\temp
Сообщение This is a file transfer that uses the Background Intelligent Transfer service (BITS) говорит о том, что начато скачивание указанного файла по протоколу BITS.
В данном примере командлет выполняет загрузку файла в синхронном режиме. Закачка файла напоминает обычную процедуру копирования через проводник или с помощью PowerShell командлета Copy-Item. При это на экран выводится прогресс бар, отображающий статус выполнения закачки. При перезагрузке компьютера, закачка возобновлена не будет (вам заново скачивать весь файл).
Используем BITS для асинхронного копирования больших файлов по сети
Процесс загрузки файлов через BITS можно запустить и в асинхронном режиме, для этого к рассмотренной выше команде нужно добавить параметр –asynchronous. В этом режиме, если что-то случится в процессе загрузки файла (перезагрузка сервера, клиента, обрыв канала связи и пр.), задание автоматически продолжится после восстановления доступности источника и загрузка файла продолжится с момента прерывания связи.
Start-BitsTransfer -source _http://10.2.2.148/erd65_32.iso -destination c:\temp -asynchronous
Start-BitsTransfer -source _http://10.2.2.148/erd65_32.iso -destination c:\temp -asynchronous -Priority low
Асинхронное задание BITS выполняется в фоновом режиме, а на экран не выводится процесс выполнения команды загрузки файла. Статус задания BITS можно получить из консоли PowerShell с помощью команды Get-BitsTransfer:
Get-BitsTransfer | fl
Команда возвращает статус передачи (в данном случае видно, что передача окончена -Transferred), информацию о количестве переданных байт, общем размере файла, времени создания и завершения задания BITS.
Вы можете просмотреть статус всех заданий BITS, запущенных на компьютере, в табличной форме:
Get-BitsTransfer | select DisplayName, BytesTotal, BytesTransferred, JobState | Format-Table -AutoSize
При использовании асинхронного режима передачи, в целевом каталоге создается временный файл с расширением TMP (по умолчанию скрыт в проводнике). Чтобы конвертировать его в исходный тип файла (который хранится на сервере-источнике), нужно выполнить команду Complete-BitsTransfer:
Задание загрузки BITS после этого считается завершенным и пропадает из списка заданий.
Вы можете загрузить локальный файл в общую сетевую папку на удаленном сервере. Для этого используется следующая команда (для удобства можно указать имя задания копирования):
Start-BitsTransfer -Source C:\iso\w101809.iso -Destination \\ekt-fs1\iso -Asynchronous -DisplayName CopyISOtoEKT
Чтобы временно приостановить задание BITS, выполните:
Get-BitsTransfer -Name CopyISOtoEKT | Suspend-BitsTransfer
Для продолжения задания используется командлет Resume-BitsTransfer:
Get-BitsTransfer -Name CopyISOtoEKT | Resume-BitsTransfer -Asynchronous
Вы можете добавить в задание BITS дополнительные файлы с помощью командлета Add-BitsFile:
Get-BitsTransfer -Name CopyISOtoEKT | Add-BitsFile -Source C:\iso\w10msu\* -Destination \\ekt-fs1\iso -Asynchronous
Чтобы удалить все задания загрузки BITS на компьютере (в том числе запущенные другими пользователями), выполните команду:
Если сервер, на котором хранится файл, требует аутентификации пользователя, вы можете вызвать окно, в котором нужно указаны учетные данные для доступа к ресурсу:
Start-BitsTransfer -source _http://10.2.2.148/erd65_32.iso -destination c:\temp -asynchronous -Priority low -Authentication NTLM -Credential Get-Credential
Чтобы было удобнее отслеживать результаты выполнения задания BITS, можно воспользоваться простым скриптом, который отслеживает выполнение задания и раз в несколько секунд выводит процент выполнения загрузки на экран. По окончании загрузки файла, скрипт автоматически преобразует TMP файл в исходный формат:
Import-Module BitsTransfer
$job = Start-BitsTransfer -Source _http://10.2.2.148/erd65_32.iso -Destination c:\temp -Asynchronous
while( ($job.JobState.ToString() -eq ‘Transferring’) -or ($job.JobState.ToString() -eq ‘Connecting’) )
<
Write-host $Job.JobState.ToString()
$Pro = ($job.BytesTransferred / $job.BytesTotal) * 100
Write-Host $Pro “%”
Sleep 3
>
Complete-BitsTransfer -BitsJob $job
Копирование всего содержимого общей сетевой папки через BITS
Как мы уже говорили, для работы BITS не нужен Web сервер, это означает, что вы можем скопировать файлы непосредственно с других Windows-компьютеров или общих сетевых папок:
Start-BitsTransfer -Source \\msk-rep01\os\rhel-server-7.0-x86_64-dvd.iso -Destination c:\temp -Asynchronous
Командлеты модуля BitsTransfer не умеют рекурсивно копировать все файлы и папки из определённой директории, или файлы, которые используются другими программами. Чтобы из указанной сетевой папки скопировать все файлы с подкаталогами, воспользуемся такой функцией (можно предварительно проверить, существует ли целевой каталог и создать его):
Import-Module BitsTransfer
$Source=»\\msk-rep01\os\»
$Destination=»c:\tmp\»
if ( -Not (Test-Path $Destination))
<
$null = New-Item -Path $Destination -ItemType Directory
>
$folders = Get-ChildItem -Name -Path $source -Directory -Recurse
$job = Start-BitsTransfer -Source $Source\*.* -Destination $Destination -asynchronous -Priority low
while( ($job.JobState.ToString() -eq ‘Transferring’) -or ($job.JobState.ToString() -eq ‘Connecting’) )
<
Sleep 3
>
Complete-BitsTransfer -BitsJob $job
foreach ($i in $folders)
<
$exists = Test-Path $Destination\$i
if ($exists -eq $false)
$job = Start-BitsTransfer -Source $Source\$i\*.* -Destination $Destination\$i -asynchronous -Priority low
while( ($job.JobState.ToString() -eq ‘Transferring’) -or ($job.JobState.ToString() -eq ‘Connecting’) )
<
Sleep 3
>
Complete-BitsTransfer -BitsJob $job
>
Загрузка файла на HTTP сервер с помощью PowerShell и BITS
С помощью BITS вы можете не только скачать файл с HTTP сервера, но и загрузить его на удаленный веб сервер. Для этого на стороне получателя должен быть установлен веб сервер IIS с установленным компонентом Bits Server Extension. В настройках виртуального каталога IIS в секции Bits Uploads нужно включить опцию «Allow clients to uploads files».
Если вы используете анонимную авторизацию, необходимо разрешить анонимным пользователям запись в каталог на уровне NTFS. Если загрузка файлов выполняется под авторизованными пользователями, им необходимо предоставить RW разрешения на папку загрузки.
Чтобы загрузить файл на HTTP сервер с помощью протокола BITS, выполните команду:
Start-bits –source c:\iso\win2016.iso -destination http://10.10.1.200/MEDVImages/win2016.iso –Transfertype Upload
Таким образом, использование возможностей BITS представляет собой отличную альтернативу традиционному копированию файлов по сети по протоколу SMB. В отличии от последнего, задание копирования файлов BITS выполняется несмотря на разрывы связи и перезагрузки компьютеров, и не так загружает канал связи, не мешая работе других сетевых приложений и пользователей. Протокол BITS может быть оптимальным решением для передачи по WAN сети больших файлов ISO образов и файлов виртуальных машин (vmdk, vhdx).
Copy-Item копирование файлов и папок из PowerShell
PowerShell командлет Copy-Item используется для копирования файлов между локальными, сетевыми каталогами или между компьютерами по сети через WinRM. Командлет Copy-Item предоставляет большое количество опций, которые можно использовать в разных сценариях копирования файлов и каталогов (по своим возможностям этот командлет почти не уступает утилите robocopy). Например:
- перезапись файлов (override)
- фильтрация по имени/шаблону
- исключение по имени/шаблону
- Verbose режим
- Копирование файлов с/на удаленные компьютеры
Начнем с простых примеров использования Copy-Item и будем переходить к более сложным.
Копирование файлов и каталогов
Чтобы скопировать один файл 1.txt из каталога C:\SourceFolder\ в F:\DestFolder\, выполните:
Copy-Item -Path «C:\SourceFolder\1.txt» -Destination «F:\DestFolder\1.txt»
Можно использовать сокращенный синтаксис командлета, пропустив указание параметров Path и Destination:
cpi «C:\SourceFolder\1.txt» «F:\DestFolder\1.txt»
Теперь скопируем каталог C:\SourceFolder\folder в F:\DestFolder\folder. В папке folder находится файл 1.txt. Обратите внимание что без ключа –Recurse, папка folder копируется без содержимого:
Copy-Item -Path «C:\SourceFolder\folder» -Destination «F:\DestFolder\folder» -Recurse
С помощью Copy-Item также можно просто объединить файлы из несколько директорий в одну (слияние директории), для этого нужно перечислить директории в ключе –Path:
Copy-Item -Path «C:\SourceFolder\*», «C:\SourceFolder2\*», «C:\SourceFolder3\*» -Destination «F:\DestFolder\»
Копирование с заменой и копирование с заменой read-only файлов
Copy-Item по умолчанию при копировании заменяет файлы в целевом каталоге. Никаких дополнительных параметров указывать не нужно. При копировании каталога, если нужно заменить каталог в целевой папке, нужно использовать ключ –Force, иначе будет ошибка “Элемент folder с указанным именем уже существует — DirectoryExists”.
Для перезаписи файла с атрибутом read-only, нужно использовать ключ -Force. Если его не использовать, вы получите ошибку “отказано в доступе по пути… CopyFileInfoItemUnauthorizedAccessError”.
Чтобы скопировать файл с перезаписью файла с read-only атрибутом используйте параметр Force.
Copy-Item -Path «C:\SourceFolder\1.txt» -Destination «F:\DestFolder\1.txt» -Force
Чтобы Copy-Item скопировал файлы из одной папки в другую без замены существующих файлов, можно использовать этот простой скрипт
Copy-Item (Join-Path «C:\SourceFolder\» «*») «F:\DestFolder\» -Exclude (Get-ChildItem «F:\DestFolder\») -Recurse
Этот скрипт скопирует все файлы и папки из C:\SourceFolder в F:\DestFolder без замены файлов уже существующих в F:\DestFolder
Копирование с фильтрацией по шаблону
С помощью Copy-Item можно скопировать файлы/директории выбранные с помощью wildcard символа * или с помощью символа ?. Также поддерживаются некоторые регулярные выражения
- * — обозначает любое количество любых символов
- ? – обозначает 1 любой символ
- [a-z], [0-9] – символы между a-z и цифры между 0 и 9
Для примера возьмём такую структуру файлов:
Выполним копирование командой:
Copy-Item -Path «C:\SourceFolder\fol*» -Destination «F:\DestFolder\»
Результат в F:\DestFolder\
Теперь чистим папку назначения и выполняем:
Copy-Item -Path «C:\SourceFolder\folder3» -Destination «F:\DestFolder\»
Папка без цифры в окончании не скопировалась, потому что folder1 подразумевает что после folder будет как минимум еще 1 символ между 0 и 3
Исключение файлов при копировании
С помощью ключа –Exclude можно исключить файлы при копировании. Например, следующай команда скопирует все файлы кроме файлов с расширением txt.
Copy-Item -Path «C:\SourceFolder\*» -Destination «F:\DestFolder\» -Recurse -Force -Exclude «*.txt»
Аналогичным же образом можно применить ключ –Include, например
Copy-Item -Path «C:\SourceFolder\*» -Destination «F:\DestFolder\» -Recurse -Force -Include «*.txt»
Скопирует только txt файлы. Хотя для простоты гораздо удобнее использовать при копировании вид -Path «C:\SourceFolder\*.txt» .
Копирование файлов на удаленный компьютер по сети
Copy-File может копировать не только по SMB протоколу, но и через WinRM (WSMan).
Создайте новую сессию с компьютером testnode1 и выполните копирование в её контексте:
$session = New-PSSession -ComputerName testnode1
Copy-Item -Path «C:\SourceFolder\*» -ToSession $session -Destination «C:\SourceFolder\» -Recurse -Force
Эта команда скопирует файлы с локального компьютера из директории C:\SourceFolder на компьютер testnode1 в C:\SourceFolder\.
Test-WSMan -ComputerName testnode1
Если WSMan не настроен, вы можете выполнить его быструю конфигурацию. Для этого откройте командную строку с правами администратора и выполните winrm quickconfig
Также можно копировать и через обычные сетевые SMB шары, для этого просто используйте UNC формат сетевого пути.
Copy-Item -Path «C:\SourceFolder\*» -Destination «\\testnode1\C$\copy_tutorial\»
Можно скопировать файл с удаленного компьютера. Принцип такой же, как и при копировании файлов на удаленный компьютер, за исключением параметра –ToSession, вместо него нужно использовать –FromSession:
$session = New-PSSession -ComputerName testnode1
Copy-Item -FromSession $session -Path «C:\SourceFolder\*» -Destination «F:\DestFolder\» -Recurse -Force
Эта команда скопирует содержимое папки C:\SourceFolder\ с компьютера testnode1 на локальный компьютер в директорию F:\DestFolder
Ключ PassThru
Командлет Copy-Item (как и многие другие командлеты PowerShell) не возвращает результатов в консоль. Параметр PassThru применяется скриптах, или для лог-файлов, когда нужно получить список скопированных файлов и работать с ним дальше. Рассмотрим пример
$items = Copy-Item -Path «C:\SourceFolder\*» –Destination «\\testnode1\C$\copy_tutorial\» -PassThru
Переменная $items будет содержать список скопированных файлов, с которым вы можете работать дальше.Это значит что вы можете напрямую работать с этими файлами. Например выполнив команду Remove-Item $items[0] , вы удалите директорию folder.
Ключ Verbose
При использовании ключа -Verbose вы получите подробный лог операций копирования. Например, вывод команды
Copy-Item -Path «C:\SourceFolder\*.txt» -Destination «F:\DestFolder\» -Recurse -Force -Verbose
Несколько полезных скриптов с Copy-Item
Скопировать только файлы:
Get-ChildItem «C:\SourceFolder» -File -Recurse | Copy-Item -Destination «F:\DestFolder»
Скопировать структуру папок, без файлов:
$path = Get-ChildItem «C:\SourceFolder» -Recurse | ?<$_.PsIsContainer -eq $true>
$dest = «F:\DestFolder\»
$parent = $path[0].Parent.Name
$path | foreach <
$_.FullName -match «$parent.+»
New-Item -ItemType directory ($dest + $Matches[0])
>
Copy-Item очень простой и удобный в использовании командлет PowerShell для выполнения операций копирования и перемещения файлов. В сочетании с другими инструментами PowerShell, Copy-Item также является мощным инструментом для написания скриптов.