Если вам нужно скачать (передать) большой файл на удаленный компьютер, не нагружая канал передачи данных, рекомендуем воспользоваться протоколом BITS. BITS (Background Intelligent Transfer service) – это встроенная служба Windows для передачи файлов между компьютерами, которая поддерживает асинхронный режим, работу в фоне, поддерживает докачку файлов, может использовать незадействованную пропускную способность сети и динамически изменять скорость загрузки. Таким образом BITS позволяет эффективно передавать большие файлы по нестабильному или медленному каналу, не влияя на трафик других сетевые приложений. В этой статье мы рассмотрим, как скачивать и передавать файлы между компьютерами по протоколу BITS с помощью PowerShell.
Как скачать файл с помощью PowerShell модуля BitsTransfer?
Для управления заданиями BITS можно использовать встроенный PowerShell модуль BitsTransfer.
Чтобы скачать ISO, который хранится на веб сервере IIS с помощью протокола BITS, выполните команду:
Start-BitsTransfer –source _http://testsite.contoso.com/netinst.iso -destination c:\temp
Клиент BITS скачает файл в синхронном режиме и сохранит его в указанный локальный каталог. На экране появится полоса, показывающая процесс загрузки. При потере подключения докачка файла не выполняется (придется заново скачивать весь файл целиком). Т.е. команда загрузки в таком режиме аналогична скачиванию файла с сайта с помощью Invoke-WebRequest.
Асинхронная загрузка файлов с докачкой по протоколу BITS
Для загрузки файлов по BITS в асинхронном режиме (с докачкой), нужно добавить параметр –asynchronous:
Start-BitsTransfer –source _http://testsite.contoso.com/netinst.iso -destination c:\temp -asynchronous
Асинхронное задание BITS будет автоматически продолжено при обрывах соединениях или перезагрузке источника или приемника.
По умолчанию задание BITS занимает всю доступную ширину канала связи (режим Foreground). Чтобы задание BITS использовало только неиспользуемую емкость канала связи, нужно добавить параметр -Priority low. В этом случае задание загрузки BITS не будет конкурировать за канал передачи с другими сервисами.
Управление заданиями BITS с помощью PowerShell
Команда создаст новое задание BITS, которое будет выполняться в фоновом режиме. Чтобы проверить статус заданий загрузки BITS, выполните команду:
Get-BitsTransfer | fl
Команда возвращает статус передачи (в данном случае передача окончена, Transferred), информацию о количестве переданных байт, общем размере файла, времени создания и завершения задания BITS.
Получить статус всех фоновых заданий BITS на компьютере:
Get-BitsTransfer | select DisplayName, BytesTotal, BytesTransferred, JobState | Format-Table -AutoSize
После завершения загрузки файла, нужно выполнить команду:
Get-BitsTransfer| where JobState -eq 'Transferred'| Complete-BitsTransfer
Если этого не сделать, клиент BITS не переименует автоматически временный файл с расширением TMP в целевом каталоге в исходное имя файла.
С помощью BITS можно копировать файлы не только по HTTP, но и по-обычному SMB протоколу Windows. Чтобы скопировать файл на удаленный компьютер в административную шару C$ или в общую сетевую папку, нужно указать UNC путь:
Start-BitsTransfer -Source C:\iso\win11.iso -Destination \\srv01\c$\iso -Asynchronous -DisplayName CopyISOtoSRV
Вы можете временно приостановить задание BITS:
Get-BitsTransfer -Name CopyISOtoSRV| Suspend-BitsTransfer
Возобновить загрузки файла:
Get-BitsTransfer -Name CopyISOtoSRV| Resume-BitsTransfer -Asynchronous
Если нужно выполнить аутентификацию на удаленном сервере для доступа к файлу, используйте команду:
Start-BitsTransfer -source _http://10.2.2.148/erd65_32.iso -destination c:\temp -asynchronous -Priority low -Authentication NTLM -Credential Get-Credential
Следующий PowerShell скрипт можно использовать для отслеживания статуса задания загрузки большого файла. На экран будет выводиться процент выполнения загрузки, а после окончания задания файл переименует TMP файл в исходный формат
$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 широко используется для фоновой передачи файлов в Windows сетях. Именно этот протокол используется для загрузки обновления через Windows Update (в том числе с сервера обновлений WSUS). Задание копирования файла через 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 ничего нет. Будем мучить..
Делал для себя скрипт с консольным интерфейсом для упрощения работы с BITS. Правда, без поддержки HTTP/HTTPS, нужды не было. Может кому пригодится.
https://drive.google.com/file/d/1LF5rTb9Z0kosgJSxhEd0K8qF53JH2FRd/view?usp=drive_link
Вот чуть переработал
function New-BitsTransfer {
param(
[Parameter (Mandatory=$true, Position=0)]
[string]$Source,
[Parameter (Mandatory=$true, Position=1)]
[string]$Destination,
[Parameter (Mandatory=$true, Position=2)]
[String]$Name,
[ValidateSet("Foreground", "High", "Normal", "Low")]
[String]$Priority="Foreground"
)
$job = Start-BitsTransfer -Source $Source -Destination $Destination -Asynchronous -Priority $Priority -DisplayName $Name
while($job.JobState.ToString() -ne 'Transferred')
{
For ($p=0; $p -lt 100) {
$p=[Math]::Floor(($job.BytesTransferred / $job.BytesTotal)*100) #округдение процентов в меньшую сторону
Start-Sleep -seconds 1
Write-Progress -Activity "Progress to 100%" -Status "Current Copying: $p %" -PercentComplete $p -CurrentOperation "Copying ..."
}
}
Start-Sleep -seconds 1
Write-host "Complete Bits-Transfer" -ForegroundColor Green
Complete-BitsTransfer -BitsJob $job
}