BITSはMicrosoftがWindowsに標準機能として載せている分散ダウンロード機能です。WindowsUpdateもバックグラウンドでBITSを利用しており、LAN内の複数のPCからWindowsUpdateをダウンロードする場合には、他のパソコンが自動的にキャッシュサーバーとなることで、インターネットとの通信負荷を押させてくれます。このBITSはWindowsUpdate専用の機能というわけではなく、簡単なプログラムを用意すれば、大容量ファイルを配布するときに自由に活用することができます。
昨今、プログラムやセキュリティパッチのフットプリント(ファイルサイズ)が大きく鳴り続ける、パッチ配布のネットワーク負荷が原因でインターネットが輻輳するなんて事件もありましたね。社内ネットワーク(WAN)はその構造上、どうしても一か所に負荷が集中しやすく、分散ダウンロードができると随分と助かりますね。
BITSでダウンロードするための一連の流れは次のようになります。
- HTTPサーバー上にダウンロード元となるファイルを用意します。
- Start-BitsTransferでBITSに新しいダウンロード要求を登録します。
- 定期的にGet-BitsTransferを呼び出しダウンロードの完了を待ちます。
- ダウンロード完了後にComplete-BitsTransferでファイルに書き出します。
上記をPowershell Scriptで記述したのが下記です。このスクリプトをダウンロードが完了するまで定周期で実行します。
$displayName = 'BITS_Sample'; # BITSにダウンロード要求を登録する時の表示名 $fromURL = 'http://www.example.co.jp/BITS_Sample.zip'; # ダウンロード元のURL $destFile = 'C:\TEMP\BITS_Sample.zip'; # ダウンロード先のファイル名 $logFile = 'C:\TEMP\BITS_Sample.log' # ログ出力先のファイル名 $noBitsInstance = $true; $completeDownload = $false; Add-Content -Path $logFile -Value ('Start Script:' + (Get-Date)); # ダウンロード先フォルダが無ければ作成しておく if ($false -eq (Test-Path 'C:\TEMP')){ mkdir 'C:\TEMP'; } # ダウンロードファイルが if ($false -eq (Test-Path $destFile)){ # BITSへのダウンロード要求を列挙する Get-BitsTransfer | Where-Object { Add-Content -Path $logFile -Value ('BITS Status:' + $_.DisplayName + '-' + $_.JobState); # 表示名の一致しているダウンロード要求が転送終了になるまで待機 if ($_.DisplayName -eq $displayName){ $noBitsInstance = $false; if ($_.JobState -eq "Transferred") { # ダウンロード完了した転送要求を完了させる Complete-BitsTransfer $_; $completeDownload = $true; } } } # BITSにダウンロード要求が登録されていなければ、新たに登録する。 if ($noBitsInstance -eq $true){ $delayMinute = Get-Random -Maximum 240; $kickDateTime = (Get-Date).AddMinutes($delayMinute); # 新規ダウンロード登録までランダムに待機する Add-Content -Path $logFile -Value ('Wait ' + $delayMinute + ' Minutes'); While ($kickDateTime -ge (Get-Date)){ Add-Content -Path $logFile -Value ('delay - ' + (Get-Date)); sleep 60; } # 新規にダウンロードを登録する Add-Content -Path $logFile -Value ('Start BitsTransfer:' + $displayName + '-' + $destFile); Start-BitsTransfer -Source $fromURL -Destination $destFile -Asynchronous -Priority Normal -DisplayName $displayName } if ($completeDownload -eq $true){ # ダウンロード完了後の処理 Add-Content -Path $logFile -Value ('Complte Download:' + $displayName + '-' + $destFile); } } Add-Content -Path $logFile -Value ('End Script:' + (Get-Date));
私はActive Directoryのグループポリシーでログオンスクリプトとして登録しました。コントロールパネルのタスクで定周期に起動してもよいでしょう。
BITSで使用する帯域の制限などはレジストリに記述するか、ActiveDirectoryのグループポリシーで定義します。