我正在开发一个 powershell 脚本,它将通过代理从 HTTP 服务器下载文件并在服务器上包含 UN/PW。
我的文件下载得很好,但有些文件非常大,所以我添加了一个函数来检查文件是否已更改(检查大小)。这在第一个文件上有效。但它在第二个文件的这一行超时了:
$test = $wc2.OpenRead($source) | Out-Null)
我的脚本代码(不包括凭证)如下所示。如果您能提供建议,告诉我如何正确关闭连接(我怀疑没有发生这种情况),或者如何使用 Powershell 通过 HTTP 获取远程文件的大小,我将不胜感激。
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"
}
}
}
答案1
我无法就这个特定问题本身发表评论,但我想提供一些一般性建议。过去几年,我编写了一些非常关键的 PS 代码,其中一些通过 HTTPS 与远程遥测设备交互。这些代码要么成功,要么失败,并且日志记录非常详细。这些代码虽然在 Windows VM 中运行,但被视为“嵌入式系统/设备”。
我真诚地建议在脚本中添加错误处理代码。诚然,互联网上充斥着 PowerShell 代码的 bang-bang-bang 示例,每个后续步骤都假设前一个步骤成功。过度使用 PS 管道有时会使情况变得更糟,例如:enumerate-something | foreach-object{ do-something },其中一些 do-something 会失败,这意味着您经常处于无法回滚的境地。
好了,废话不多说了。建议:
- 启用严格模式。这将防止任何无意的类型转换/强制转换。使用正确的类型定义预先声明变量。
- 尽可能使用 -erroraction silentlyContinue,并使用“if ($?)”检查捕获错误...或使用 try{} catch{} 结构包装生成异常的调用。并非所有 PS 函数都会引发异常!
- 写入大量日志数据
- 识别更有可能失败的操作并尽可能编写重试逻辑。
我就到此为止!
祝你好运。
答案2
您的问题是由于 $test 变量被分配了一个空值。
当你建立变量 $test
$test = $wc2.OpenRead($source) | Out-Null
“| Out-Null”部分使结果为空,导致将 null 分配给 $test,将其删除,这样就不会出现问题了。
关于您关于关闭 System.Net.WebClient 连接的问题,顺便说一下:您无需采取行动,所有 HTTP 连接都会在需要时关闭,并且不会干扰建立第二个连接。打开持久连接将允许在与同一 URL 的后续连接上更及时、更高效地建立连接。有关持久 HTTP 连接的更多信息,请参见这里。