Повторите попытку передачи файла BITS при неудачных загрузках с помощью Powershell

#powershell #microsoft-bits

#powershell #microsoft-bits

Вопрос:

Я выполняю передачу BITS ежедневных изображений с веб-сервера, и я продолжаю получать случайные удаления во время передачи.

При циклическом просмотре загрузок я время от времени получаю сообщение «Соединение было закрыто преждевременно» или «Произошла ошибка в службе поддержки защищенного канала». В каждой папке около 180 изображений, и это происходит, возможно, для 5-10% из них. Мне нужно повторить попытку загрузки для тех, которые не завершились.

Мой код для этого следующий — мой несовершенный обходной путь — запустить цикл дважды, но я надеюсь найти лучшее решение.

 # Set the URL where the images are located
$url = 'https://www.nrlmry.navy.mil/archdat/global/stitched/MoS_2/navgem/wind_waves/latest/'

# Set the local path where the images will be stored
$path = 'C:imagesWind_Waveslatest'

# Create a list of all assets returned from $url
$site = Invoke-WebRequest -UseBasicParsing -Uri $url

# Create a table subset from the $site of all files returned with a .jpg extension
$table = $site.Links | Where-Object{ $_.tagName -eq 'A' -and $_.href.ToLower().EndsWith("jpg") }

# Create a list of all href items from the table amp; call it $images
$images = $table.href 

# Enumerate all of the images - for troubleshooting purposes - can be removed
$images

# Check to make sure there are images available for download - arbitrarily picked more than 2 $images
if($images.count -gt 2){

    # Delete all of the files in the "latest" folder
    Remove-Item ($path   "*.*") -Force
# For loop to check to see if we already have the image and, if not, download it
ForEach ($image in $images)
{
if(![System.IO.File]::Exists($path   $image)){
    Write-Output "Downloading: " $image
    Start-BitsTransfer -Source ($url   $image) -Destination $path -TransferType Download -RetryInterval 60
    Start-Sleep 2
    }
}
Get-BitsTransfer | Where-Object {$_.JobState -eq "Transferred"} | Complete-BitsTransfer
} else {
Write-Output "No images to download"}
  

Ответ №1:

Я не вижу никакой обработки ошибок в вашем коде для возобновления / повторной попытки / перезапуска при сбое.

  1. Значение, почему нет try / catch в цикле или Get?
  2. Если Get включен для каждого задания загрузки в цикле, почему он находится вне цикла?

Загрузка используется по умолчанию для TransferType, поэтому указывать не нужно, обычно при этом генерируется ошибка.

Итак, что-то вроде этого. Я проверил это, но никогда не получал сбоя. Тем не менее, у меня очень высокоскоростное подключение к Интернету. Если вы делаете это внутри предприятия, пограничные устройства (фильтры, прокси-серверы, также могут замедлять работу, потенциально вызывая тайм-ауты.)

 $url  = 'https://www.nrlmry.navy.mil/archdat/global/stitched/MoS_2/navgem/wind_waves/latest/'
$path = 'D:TempimagesWind_Waveslatest'
$site = Invoke-WebRequest -UseBasicParsing -Uri $url

# Create a table subset from the $site of all files returned with a .jpg extension
$table = $site.Links | 
Where-Object{
    $_.tagName -eq 'A' -and 
    $_.href.ToLower().EndsWith('jpg') 
}

<#
# Create a list of all href items from the table amp; call it $images
Enumerate all of the images - for troubleshooting purposes - can be removed
Assign and display using variable squeezing
#>
($images = $table.href)

<#
Check to make sure there are images available for download - arbitrarily 
picked more than 2 $images
#>
if($images.count -gt 2)
{
    Remove-Item ($path   '*.*') -Force
    ForEach ($image in $images)
    {
        Try
        {
            Write-Verbose -Message "Downloading: $image" -Verbose

            if(![System.IO.File]::Exists($path   $image))
            {
                $StartBitsTransferSplat = @{
                    Source              = ($url   $image) 
                    Destination         = $path 
                    RetryInterval       = 60
                }
                Start-BitsTransfer @StartBitsTransferSplat -ErrorAction Stop
                Start-Sleep 2
            }

            Get-BitsTransfer | 
            Where-Object {$PSItem.JobState -eq 'Transferred'} | 
            Complete-BitsTransfer
        }
        Catch
        {
            $PSItem.Exception.Message
            Write-Warning -Message "Download of $image not complete or failed. Attempting a resume/retry" -Verbose
            Get-BitsTransfer -Name $image | Resume-BitsTransfer

        }
    }
} 
else 
{
    Write-Warning -Message 'No images to download'
    $PSItem.Exception.Message
}
  

Смотрите файлы справки

Модуль Resume-BitsTransfer: bitstransfer возобновляет задание по передаче BITS.

 # Example 1: Resume all BITS transfer jobs owned by the current user
Get-BitsTransfer | Resume-BitsTransfer

# Example 2: Resume a new BITS transfer job that was initially suspended
$Bits = Start-BitsTransfer -DisplayName "MyJob" -Suspended
Add-BitsTransfer -BitsJob $Bits  -ClientFileName C:myFile -ServerFileName http://www.SomeSiteName.com/file1
Resume-BitsTransfer -BitsJob $Bits -Asynchronous

# Example 3: Resume the BITS transfer by the specified display name
Get-BitsTransfer -Name "TestJob01" | Resume-BitsTransfer
  

Комментарии:

1. Спасибо за это! При сбое загрузки я получаю следующее сообщение об ошибке в разделе Catch: «ПРЕДУПРЕЖДЕНИЕ: загрузка wind_waves_2020090300_0034.jpg не завершено или сбой. Попытка возобновить / повторить Get-BitsTransfer: не удается найти передачу битов с именем ‘wind_waves_2020090300_0034.jpg . Вы можете использовать командлет Get-BitsTransfer без каких-либо параметров для просмотра списка текущих передач битов. ПОДРОБНО: Загрузка: wind_waves_2020090300_0035.jpg Произошла ошибка в службе поддержки защищенного канала»

2. Не беспокойтесь. Как я уже говорил, у меня очень высокоскоростное соединение, а не шлюзы / фильтрация, поэтому я никогда не попадал в область ошибок. Тем не менее, вся эта ошибка означает, что имя при проверке задания недопустимо. Итак, это означает, что вам нужно перехватить имя задания в сеансе отладки, чтобы выяснить, что это может быть, или вместо этого использовать идентификатор задания.

3. Я оборачиваю раздел Try-Catch в цикле do-while со счетчиком, чтобы передача BITS повторялась до 5 раз.

Ответ №2:

Вот несколько измененная версия приведенного выше кода. Похоже, что объект задания BITS transfer исчезает при возникновении ошибки, поэтому нет смысла пытаться найти / возобновить это задание. Вместо этого я заключил весь блок Try-Catch в цикл while с завершением при загрузке файла.

 $url = 'https://www.nrlmry.navy.mil/archdat/global/stitched/MoS_2/navgem/wind_waves/latest/'
$path = 'D:TempimagesWind_Waveslatest'
$site = Invoke-WebRequest -UseBasicParsing -Uri $url
$MaxRetries = 3     # Initialize the maximum number of retry attempts.

# Create a table subset from the $site of all files returned with a .jpg extension
$table = $site.Links | 
Where-Object {
    $_.tagName -eq 'A' -and 
    $_.href.ToLower().EndsWith('jpg') 
}

<#
# Create a list of all href items from the table amp; call it $images
Enumerate all of the images - for troubleshooting purposes - can be removed
Assign and display using variable squeezing
#>
($images = $table.href)

<#
Check to make sure there are images available for download - arbitrarily 
picked more than 2 $images
#>
if ($images.count -gt 2) {
    Remove-Item ($path   '*.*') -Force
    ForEach ($image in $images) {
        # Due to occasional failures to transfer, wrap the BITS transfer in a while loop
        # re-initialize the exit counter for each new image
        $retryCount = 0
        while ($retryCount -le $MaxRetries){
            Try {
                Write-Verbose -Message "Downloading: $image" -Verbose

                if (![System.IO.File]::Exists($path   $image)) {
                    $StartBitsTransferSplat = @{
                        Source        = ($url   $image) 
                        Destination   = $path 
                        RetryInterval = 60
                    }
                    Start-BitsTransfer @StartBitsTransferSplat -ErrorAction Stop
                    Start-Sleep 2
                }

                # To get here, the transfer must have finished, so set the counter
                # greater than the max value to exit the loop
                $retryCount = $MaxRetries   1
            } # End Try block

            Catch {
                $PSItem.Exception.Message
                $retryCount  = 1
                Write-Warning -Message "Download of $image not complete or failed. Attempting retry #: $retryCount" -Verbose
            } # End Catch Block
            
        } # End While loop for retries

    } # End of loop over images

} # End of test for new images
else {
    Write-Warning -Message 'No images to download'
    $PSItem.Exception.Message
} # End of result for no new images
  

Комментарии:

1. Иногда передача зависает на полпути во время передачи и не продвигается вперед — в таких случаях система остается зависшей около часа, прежде чем выдает ошибку и пытается снова. Есть ли способ перехватить эти зависшие передачи и принудительно повторить попытку через x секунд?

Ответ №3:

Вот комбинация кода, предоставленного postanote, и цикла выполнения во время выполнения, чтобы повторить загрузку до 5 раз, если выдается ошибка.

 $url  = 'https://www.nrlmry.navy.mil/archdat/global/stitched/MoS_2/navgem/wind_waves/latest/'
$path = 'D:TempimagesWind_Waveslatest'
$site = Invoke-WebRequest -UseBasicParsing -Uri $url

# Create a table subset from the $site of all files returned with a .jpg extension
$table = $site.Links | 
Where-Object{
    $_.tagName -eq 'A' -and 
    $_.href.ToLower().EndsWith('jpg') 
}

<#
# Create a list of all href items from the table amp; call it $images
Enumerate all of the images - for troubleshooting purposes - can be removed
Assign and display using variable squeezing
#>

($images = $table.href)

 <# Check to make sure there are images available for download - arbitrarily 
    picked more than 2 $images #>

    if($images.count -gt 2)
    {
        Remove-Item ($path   '*.*') -Force
        ForEach ($image in $images)
        {
            # Create a Do-While loop to retry downloads up to 5 times if they fail
            $Stoploop = $false
            [int]$Retrycount = "0"
            do{
            Try
            {
                Write-Verbose -Message "Downloading: $image" -Verbose
    
                if(![System.IO.File]::Exists($path   $image))
                {
                    $StartBitsTransferSplat = @{
                        Source              = ($url   $image) 
                        Destination         = $path 
                        RetryInterval       = 60
                    }
                    Start-BitsTransfer @StartBitsTransferSplat -ErrorAction Stop
                    Start-Sleep 10
                    $Stoploop = $true
                }
    
                Get-BitsTransfer | 
                Where-Object {$PSItem.JobState -eq 'Transferred'} | 
                Complete-BitsTransfer
            }
            Catch
            {
                if ($Retrycount -gt 5){
                $PSItem.Exception.Message
                Write-Warning -Message "Download of $image not complete or failed." -Verbose
                $Stoploop = $true
                }
                else {
                Write-Host "Could not download the image, retrying..."
                Start-Sleep 10
                $Retrycount = $Retrycount   1
                }
            }
        }
        While ($Stoploop -eq $false)
        }
    }
    else 
    {
        Write-Warning -Message 'No images to download'
        $PSItem.Exception.Message
    }
  

Комментарии:

1. Похоже, что прерванные передачи все еще отображаются в списке окон терминала, когда происходит повторная попытка — не уверен, что я должен сделать, чтобы исправить это (если что-нибудь)?