В локальных (да и глобальных) сетях файлы между системами обычно передаются с помощью протоколов SMB, FTP или HTTP. Проблема всех этих протоколов – сложности с докачкой больших файлов, которые могут усугубляться проблемами передачи данных по медленному или нестабильному каналу. При копировании файлов по этим протоколам обычно задействуется вся доступная пропускная способность канала связи между сервером и получателем, что может негативно сказаться на производительности сети и работе других приложения (не всегда возможно настроить корректные политики QoS на уровне сетевого оборудования). В этой статье мы рассмотрим возможность использования протокола BITS и командлетов PowerShell для копирования больших файлов через сеть по нестабильному или медленному каналу.
- Протокол BITS
- BITS: требования к ОС и версии PowerShell
- Как скачать файл по протоколу BITS с помощью PowerShell
- Синхронная передача файлов между компьютерами с помощью BITS
- Используем BITS для асинхронного копирования больших файлов по сети
- Копирование всего содержимого общей сетевой папки через BITS
- Загрузка файла на HTTP сервер с помощью PowerShell и BITS
Протокол BITS
BITS или Background Intelligent Transfer service — (Фоновая интеллектуальная служба передачи) – это служба Windows, которая используется для передачи файлов между системами. С помощью протокола BITS можно передавать как скачивать, так и закачивать файлы. Именно по этому протоколу компьютеры скачивают файлы с серверов при выполнении автоматического обновлении Windows (в т.ч. при скачивании обновлений со WSUS сервера), при получении программ с SCCM точек распространения и т.д.
Преимущества протокола BITS:
- BITS — интеллектуальный протокол, который при работе способен регулировать используемую полосу канала связи, чтобы не оказывать влияния на другие сетевые приложения и сервисы. BITS может использовать только незанятую полосу пропускания канала и динамически изменять скорость передачи данных в процессе работы (если другие приложения увеличат нагрузку на сеть, BITS может уменьшить скорость передачи данных по сети);
- Загрузка файла может идти в фоновом режиме, незаметно для пользователя;
- Задание BITS в режиме докачки будет автоматически продолжено даже в случае обрыва канали связи между компьютером и клиентом, или после перезагрузки компьютера;
- В любой момент вы можете приостановить или возобновить загрузку по BITS без потери данных;На заметку. Возможность перезапуска процедуры копирования файлов по сети имеется также и в утилите robocopy.exe, позволяющей возобновить закачку файла в случае обрыва соединения.
- BITS позволяет управлять приоритетами задач загрузки;
- Передача файлов между компьютерами происходит по портам 80 (HTTP) или 443 (HTTPS), поэтому вам не придется открывать дополнительных портов на межсетевых экранах. Например, 445 порта, по которому идет копирование при использовании протокола SMB (не забудьте, что в старых версиях протокола SMB 1.0 много уязвимостей);
- На стороне получателя и сервера не обязательно требуется наличие развернутого IIS сервера.
Таким образом, 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:
Import-Module BitsTransfer
После загрузки модуля, вы можете вывести список всех доступных команд модуля BitsTransfer:
get-command *-BITS*
Как вы видите, доступно всего 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:
Команда возвращает статус передачи (в данном случае видно, что передача окончена -Transferred), информацию о количестве переданных байт, общем размере файла, времени создания и завершения задания BITS.
Вы можете просмотреть статус всех заданий BITS, запущенных на компьютере, в табличной форме:
Get-BitsTransfer | select DisplayName, BytesTotal, BytesTransferred, JobState | Format-Table -AutoSize
При использовании асинхронного режима передачи, в целевом каталоге создается временный файл с расширением TMP (по умолчанию скрыт в проводнике). Чтобы конвертировать его в исходный тип файла (который хранится на сервере-источнике), нужно выполнить команду Complete-BitsTransfer:
Get-BitsTransfer | 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 на компьютере (в том числе запущенные другими пользователями), выполните команду:
Get-BitsTransfer -Allusers|Remove-BitsTransfer
Если сервер, на котором хранится файл, требует аутентификации пользователя, вы можете вызвать окно, в котором нужно указаны учетные данные для доступа к ресурсу:
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) {New-Item $Destination\$i -ItemType Directory}
$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).
Ух ты, как круто! Тема прям как под заказ — сейчас приходится копировать vmdk диски с виртуальными машинами в региональные филиалы по 2 Мбитному каналу. Пользуюсь wget — но по через BITS как вы показали гораздо удобнее и без всяких лишних телодвижений!
Снимаю шляпу, спс! 😉
Спасибо за статью, познавательно.
Подскажите если кто знает, передача файлов в размере 2ТВ с помощью BITS возможна?
Как бы ещё закачку из каталога оформить одной ссылкой (или запуском файла), а то простой менеджер не справится с запуском PowerShell и прочими командами, сам к сожалению скрипты писать не умею..
Сам таких больших файлов не передавал, но не думаю, что есть какие-то ограничения на этот счет. На файлы будут действовать только ограничения файловой системы NTFS.
Можно конечно к функции закачки файлов по BITS GUI прикрутить, но это уже больше к программистам…
Упростить задачу для конечных пользователей можно путем оформления этого скрипта например в файл C:\scripts\DownloadBitsFiles.ps1 и запуском его из bat/cmd файла с таким кодом:
Powershell.exe -executionpolicy remotesigned -File C:\scripts\DownloadBitsFiles.ps1
Пользователю объяснить, что каталоги откуда и куда скопировать задаются путем редактирования файла DownloadBitsFiles.ps1 в любом текстовом редакторе.
Спасибо, будем тестировать..
Если задача «тупо запускать», без изменения DownloadBitsFiles.ps1, можно в PowerGUI Script Editir собрать в exe файл.
Ну, вот когда-то писал на ту же тему
блин, уже 4 года прошло
🙂 проблема-то и предложное решение всё еще актуальны.
Многие админы 4 года назад даже и не думали как много всего можно реализовать на PoSh
С помощью вашего скрипта запустил скачку большого количества файлов (over 10000) с удаленной системы , скрипт отработал, но при выполнении команды Get-BitsTransfer | select DisplayName, BytesTotal, BytesTransferred, JobState видно что осталось множество незаверешенных закачек BITS со статусом Transferred. Пытаюсь завершить все закачки BITS командой Get-BitsTransfer | Complete-BitsTransfer, но выдает ошибку:
PS C:\windows\system32> Get-BitsTransfer | Complete-BitsTransfer
Complete-BitsTransfer : The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
At line:1 char:20
+ Get-BitsTransfer | Complete-BitsTransfer
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Complete-BitsTransfer], FileNotFoundException
+ FullyQualifiedErrorId : System.IO.FileNotFoundException,Microsoft.BackgroundIntelligentTransfer.Management.Compl
eteBitsTransferCommand
Задания BITS не завершаются и в каталогах куча файлов с расширением TMP, причем размер файлов совпадает с размеров файлов на источнике, т.е. файлы докачались.
Подскажите, как завершить такие закачки?
Скорее всего есть задания закачки BITS с незавершенным статусом. Показать эти задания можно так:
Get-BitsTransfer | ? { $_.JobState -ne 'Transferred' }
Чтобы принудительно их завершить:
Get-BitsTransfer | ? { $_.JobState -ne 'Transferred' } | Remove-BitsTransfer
Ну и стандартно завершаем все остальные задания BITS:
Get-BitsTransfer | Complete-BitsTransfer
Доброго дня, попробовал на PoSH 5 получил вот такие вот ошибки
Невозможно вызвать метод для выражения со значением NULL.
строка:16 знак:8
+ while( ($job.JobState.ToString() -eq ‘Transferring’) -or ($job.JobSta …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Complete-BitsTransfer : Не удается проверить аргумент для параметра «BitsJob». Аргумент пустой или имее
т значение NULL. Укажите непустой аргумент, не имеющий значение NULL, после чего повторите выполнение к
оманды.
строка:20 знак:32
+ Complete-BitsTransfer -BitsJob $job
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Complete-BitsTransfer], ParameterBindingValidationExce
ption
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.BackgroundIntelligentTransfer
.Management.CompleteBitsTransferCommand
Есть программа со времен XP robocopy. С ее помощи можно решить данную задачу.
Спасио конечно за совет по робокопям=) Мне было интересно протестировать данную технологию.
Я разобрался в чем ошибка была у меня.
Очень интересная статья!
Огромное спасибо автору за грамотную и исчерпывающую публикацию!
У меня вопрос -который не осветился в самой публикации — как на счет BITS over https. Классический http использовать как-то «не комильфо», тем более есть инфа на Wiki:
«Version 2.5 (June 2007)
Adds support for certificate-based client authentication for secure HTTP transports and custom HTTP headers.
Support for IPv6.
Available for download for Windows XP and Windows Server 2003[3] and included with Windows XP Service Pack 3»
С точки зрения пользователя, клиент в прозрачном режиме работает с любым типом сервера BITS, будь то http/https/smb. Так что трафик будет защищен, если на стороне клиента включена поддержка шифрования https
Кстати, вот еще инфа вдогонку:
«BITS suspends any ongoing transfer when the network connection is lost or the operating system is shut down. It resumes the transfer from where it left off when (the computer is turned on later and) the network connection is restored. BITS supports transfers over SMB, HTTP and HTTPS.»
Здравствуйте.
Как я понял, BITS работает на файловом уровне (т.е., манипулирует целыми файлами).
А есть какие-то нативные Windows-инструменты передачи файлов на блочном уровне (т.е., какой-л.аналог rsync)?
Заранее благодарен.
А bash в windows 10 не пробовали вроде как rsync поддерживается.
Нет, не пробовал.
Но, думаю, в моём случае (сервер 2012R2) это не применимо.
Да и хотелось чего-то «родного»… От MS.
(за совет — спасибо).
Ну если речь о синхронизации множества файлов — то вероятно стоит подумать о robocopy, хоть и не блочный режим, однако довольно шустрая утилита. Если нужно копировать в режиме синхронизации большие файлы — ничего готового вспомнить не могу
Спасибо.
Хорошо всё это, но не работает по расписанию из-под незалогиненного пользователя, и похоже не будет:
Откуда-то:
«It looks like you’re only going to be able to run that script when you’re logged in. From the MS documentation «Using Windows Powershell to Create BITS Transfer Jobs» found here.
When you use *-BitsTransfer cmdlets from within a process that runs in a noninteractive context, such as a Windows service, you may not be able to add files to BITS jobs, which can result in a suspended state. For the job to proceed, the identity that was used to create a transfer job must be logged on. For example, when creating a BITS job in a PowerShell script that was executed as a Task Scheduler job, the BITS transfer will never complete unless the Task Scheduler’s task setting «Run only when user is logged on» is enabled.»
От имени системной учетной записи ставить в планировщик надо, она автоматически в систему входит всегда.
Это бессмысленно, так как даже если под System и будет работать, то System не имеет доступа к сетевым ресурсам. А Bits нужен именно для сетевого копирования, а не локального.
А может и получится если:
1. под system действительно заработает.
2. Права на каталоги давать компьютеру, типа Server$. Вроде при этом System и работает.
Но мне вроде уже неактуально, держу на сервере постоянный логин, терпимо.
PS C:\Windows\system32> import-module BitsTransfer
$url = «https://learn.microsoft.com/en-us/azure/active-directory/hybrid/media/how-to-connect-uninstall/uninstall-4.png»
$path = «C:\windows\temp\Framework-ndp48-x86-x64-allos-enu.exe»
Start-BitsTransfer $url $path
Start-BitsTransfer : Ошибка поддержки безопасных каналов
строка:5 знак:23
+ Start-BitsTransfer <<<< $url $path
+ CategoryInfo : InvalidOperation: (:) [Start-BitsTransfer], Exception
+ FullyQualifiedErrorId : StartBitsTransferCOMException,Microsoft.BackgroundIntelligentTransfer.Management.NewBitsTransferCommand
7ка 32хразрядная с PS 2.0 так ругается… Что может быть. TLS включены в дефолт
Возможно нужно указывать TLS 1.2, т.е. сначала установить его поддержку (если не сделали еще) : https://winitpro.ru/index.php/2022/04/19/vklyuchit-protokol-tls-1-2-windows/
Чтобы для подключения использовался протокол TLS 1.2, нужно выполнить команду:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
но не знаю, будет ли это работать в PowerShell 2.0. Обновитесь вы до 5.1…
https://winitpro.ru/index.php/2020/05/14/obnovlenie-powershell-v-windows/
Это изначальная задача)) В том то и дело что, чтобы обновить, надо залить туда файл обновления и его запустить (скрипт выполняется удаленно), а во втором PS кроме как bits-transfer ничего нет. Будем мучить..