Powershell O download via HTTP usando o proxy e a verificação do tamanho do arquivo remoto falha no segundo arquivo

5

Eu tenho um script powershell que estou desenvolvendo, que fará o download de arquivos de um servidor HTTP passando por um proxy e incluindo um UN / PW no servidor.

Eu tenho arquivos baixando bem, mas alguns arquivos são muito grandes, e então eu adicionei uma função para verificar se o arquivo foi alterado (verificando o tamanho). Isso funciona no primeiro arquivo. Mas o tempo limite no segundo arquivo nesta linha:

$test = $wc2.OpenRead($source) | Out-Null)

O código do meu script, excluindo credenciais, está listado abaixo. Eu gostaria de receber conselhos sobre como fechar corretamente uma conexão (como eu suspeito que não esteja acontecendo) ou sobre como obter o tamanho de um arquivo remoto via HTTP usando o Powershell.

Function getWebClient {
    $webClient = new-object System.Net.WebClient 

    $pxy = new-object System.Net.WebProxy $proxy  
    $pxy.Credentials = New-Object System.Net.NetworkCredential ("tnad\$proxy_un", "$proxy_pw") 
    $webClient.proxy=$pxy  
    $webClient.Headers.Add("user-agent", "Windows Powershell WebClient Header") 

    $WebClient.Credentials = New-Object System.Net.Networkcredential($un, $pw)

    return $WebClient
}

foreach ($ds in $datasetsTest) {
    Write-Host "Checking: $ds"
    $source = "$server$ds"
    $dest = "$destFolder$ds"

    #Test whether the destination file already exists, if it exists, compare file sizes.
    $destExists = Test-Path $dest

    if($destExists -eq $false) {
        Try {
            $wc1 = getWebClient
            $wc1.DownloadFile($source, $dest)
            $wc1.Dispose()
            Write-Host "File downloaded"  -foregroundcolor "green"
        } Catch {
            Write-Host "Downloading $ds failed..." -foregroundcolor "red"
        }
    } else {
        $localFileSize = (Get-Item $dest).length
        $wc2 = getWebClient
        $test = $wc2.OpenRead($source) | Out-Null
        $wc2.Dispose()

        $remoteFileSize = $wc2.ResponseHeaders["Content-Length"]

        Write-Host "Local file size: $localFileSize, remote file size: $remoteFileSize"
        if(!($localFileSize -eq $remoteFileSize)) {
            #file exists, but the server version changed...
            Try {
                Remove-Item $dest
                $wc3 = getWebClient
                $wc3.DownloadFile($source, $dest) 
                $wc3.Dispose($true)
                Write-Host "File downloaded"  -foregroundcolor "green"
            } Catch {
                Write-Host "Downloading $ds failed..." -foregroundcolor "red"
            }
        } else {
            Write-Host "Skipping, file exists and hasn't changed"  -foregroundcolor "magenta"
        }
    }
}
    
por Alex Leith 01.09.2015 / 04:16

2 respostas

3

Não posso comentar este assunto em particular, mas gostaria de oferecer algumas recomendações gerais. Escrevi alguns códigos PS de missão crítica ao longo dos últimos anos, alguns dos quais interagem com equipamentos de telemetria remota via HTTPS. Esse código deve ter êxito ou falhar normalmente, com log muito detalhado. O código, embora seja executado em VMs do Windows, é tratado como "sistema / appliance incorporado".

Eu sinceramente recomendo adicionar código de tratamento de erros ao seu script. Concedido, a Internet está cheia de exemplos bang-bang-bang do código do PowerShell, com cada passo sucessivo assumindo que o anterior foi bem-sucedido. Isso às vezes é agravado pelo uso excessivo de pipelines PS, por exemplo: enumerate-something | foreach-object {do-something}, em que alguns dos algo fracassam, o que significa que você geralmente fica em uma situação de reversão impossível.

De qualquer forma, basta balbuciar. Recomendações:

  1. Ative o modo estrito. Isso evitará qualquer tipo de coerção / coerção não intencional. Pré-declare suas variáveis, com definições de tipo corretas.
  2. Use -erroraction silencentlyContinue sempre que possível e intercepte erros com "if ($?)" verifica ... ou agrupa chamadas que geram exceções com construções try {} catch {}. Nem todas as funções PS levantam exceções!
  3. Escreva vários dados de registro
  4. Identifique ações com maior probabilidade de falhar e codifique a lógica de nova tentativa sempre que possível.

Eu vou parar aí!

Boa sorte.

    
por 07.09.2015 / 23:31
2

Você emite é devido à variável $ test sendo atribuída um valor nulo.

Quando você constrói a variável $ test

$test = $wc2.OpenRead($source) | Out-Null

a parte "| Out-Null" está anulando os resultados, fazendo com que null seja atribuído a $ test, removê-lo e você não deve ter um problema.

Como um aparte para sua pergunta em fechar conexões de System.Net.WebClient: Ação em você fim não é requerido, todas as conexões HTTP são fechadas quando requerido e não deveriam interferir em estabelecer uma segunda conexão. Uma conexão persistente aberta permitirá uma conexão mais rápida e eficiente em conexões subsequentes para o mesmo URL. Mais informações sobre conexões HTTP persistentes podem ser encontradas aqui .

    
por 07.09.2015 / 21:24