【问题标题】:PowerShell script to check the status of a URL用于检查 URL 状态的 PowerShell 脚本
【发布时间】:2013-12-14 02:03:08
【问题描述】:

Similar to this question here 我正在尝试监控一组网站链接是否启动并运行或没有响应。我在 Internet 上找到了相同的 PowerShell 脚本。

但是,我需要检查更具体的链接,而不是直接的网站链接,例如:

http://mypage.global/Chemical/

http://maypage2:9080/portal/site/hotpot/

当我尝试检查这些链接的状态时,我得到以下输出:

URL    StatusCode    StatusDescription    ResponseLength    TimeTaken
http://mypage.global/Chemical/    0
http://maypage2:9080/portal/site/hotpot/    0

以上链接需要我连接到VPN,但我可以从浏览器访问这些链接。

Invoke-WebRequest -Uri https://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url 的输出:

PS C:\Users\682126> Invoke-WebRequest -Uri https://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url

The term 'Invoke-WebRequest' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

At line:1 char:18
+ Invoke-WebRequest <<<<  -Uri https://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url > tmp.txt
    + CategoryInfo          : ObjectNotFound: (Invoke-WebRequest:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

$PSVersionTable

Name                           Value
----                           -----
CLRVersion                     2.0.50727.5472
BuildVersion                   6.1.7601.17514
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1

【问题讨论】:

  • 究竟是什么给了你这样的输出?
  • 如果你这样做会发生什么?:Invoke-WebRequest -Uri http://mypage.global/Chemical/
  • Invoke-WebRequest 仅适用于 PowerShell 3。您要么必须升级到 PowerShell 3,要么找到其他方式来处理请求。
  • @Dangph 升级是不可能的,因为我没有管理员权限......还有什么其他方法可以实现?

标签: powershell web-services powershell-2.0 monitoring


【解决方案1】:

我最近设置了一个执行此操作的脚本。

正如 David Brabant 指出的那样,您可以使用 System.Net.WebRequest 类来执行 HTTP 请求。

要检查它是否可操作,您应该使用以下示例代码:

# First we create the request.
$HTTP_Request = [System.Net.WebRequest]::Create('http://google.com')

# We then get a response from the site.
$HTTP_Response = $HTTP_Request.GetResponse()

# We then get the HTTP code as an integer.
$HTTP_Status = [int]$HTTP_Response.StatusCode

If ($HTTP_Status -eq 200) {
    Write-Host "Site is OK!"
}
Else {
    Write-Host "The Site may be down, please check!"
}

# Finally, we clean up the http request by closing it.
If ($HTTP_Response -eq $null) { } 
Else { $HTTP_Response.Close() }

【讨论】:

  • 谢谢,完成了这项工作。但是,如果我要显示每个 URL 的响应时间,当 URL 启动时,我如何获得该值?
  • 要显示响应时间,您可以使用 (Measure-Command {HTTP REQUEST CODE HERE}).TotalSeconds 包装执行 Web 请求的代码部分
  • 你也可以设置 $HTTP_Request.Method="HEAD" 这只会给你没有正文的标题部分,因为没有发送正文会更快
  • 只是检查:我们应该在最后一行关闭什么,$HTTP_Response 或 $HTTP_Request?
  • $HTTP_Request,类型为System.Net.HttpWebRequest,没有成员close()
【解决方案2】:

对于拥有 PowerShell 3 或更高版本(即 Windows Server 2012+ 或带有 the Windows Management Framework 4.0 update 的 Windows Server 2008 R2)的用户,您可以执行此单行操作,而不是调用 System.Net.WebRequest:

$statusCode = wget http://stackoverflow.com/questions/20259251/ | % {$_.StatusCode}

【讨论】:

  • 可能值得强调的是 wget 是 Invoke-WebRequest 的别名(curl 和 iwr 也是如此),我发现值得学习本地名称以防您需要 Google东西。
  • 继续 Ray 的评论,我也不妨指出 % 是 ForEach-Object 的别名。字符$ 指定一个变量。 _,当跟随$时,是$PSItem的别名;这是一个自动变量 (man about_Automatic_Variables),它包含管道对象中的当前对象。这将我们带到“管道”| (man about_Pipelines) 并允许将上一个命令的输出用作下一个命令的输入。所以完整的翻译是$variable = Invoke-WebRequest http://stackoverflow.com/questions/20259251/ | ForEach-Object {$PSItem.StatusCode}
  • 最后,. 是检索对象属性 (man about_Properties) 的快捷方式。所以实际的完整翻译是$variable = Invoke-WebRequest $url | ForEach-Object {$PSItem | Select-Object -Property StatusCode}
  • 这实际上是下载文件非常糟糕。
  • 另见此帖:petri.com/testing-uris-urls-powershell 建议使用以下命令:invoke-webrequest http://stackoverflow.com/questions/20259251/ -DisableKeepAlive -UseBasicParsing -Method head
【解决方案3】:

你可以试试这个:

function Get-UrlStatusCode([string] $Url)
{
    try
    {
        (Invoke-WebRequest -Uri $Url -UseBasicParsing -DisableKeepAlive).StatusCode
    }
    catch [Net.WebException]
    {
        [int]$_.Exception.Response.StatusCode
    }
}

$statusCode = Get-UrlStatusCode 'httpstat.us/500'

【讨论】:

  • 添加 -Method head 对我来说效果更好,它更快并且避免下载... (Invoke-WebRequest -Uri $Url -UseBasicParsing -DisableKeepAlive -Method head).StatusCode 在这里使用 https://www.petri.com/testing-uris-urls-powershell 和 on SO here
  • 这对我有帮助,但请注意它在 powershell 7 中已损坏,因为抛出的异常与 powershell 5 不同,因此指定它意味着未捕获异常并将返回 0。删除 [Net. WebException] 规范使其适用于 5 和 7
【解决方案4】:
$request = [System.Net.WebRequest]::Create('http://stackoverflow.com/questions/20259251/powershell-script-to-check-the-status-of-a-url')

$response = $request.GetResponse()

$response.StatusCode

$response.Close()

【讨论】:

  • 上述代码中,哪个参数指定链接是否可操作?
  • 定义“可操作”。
【解决方案5】:

您必须将 Windows PowerShell 更新到最低版本 4.0,以下脚本才能正常工作。


[array]$SiteLinks = "http://mypage.global/Chemical/test.html"
"http://maypage2:9080/portal/site/hotpot/test.json"


foreach($url in $SiteLinks) {

   try {
      Write-host "Verifying $url" -ForegroundColor Yellow
      $checkConnection = Invoke-WebRequest -Uri $url
      if ($checkConnection.StatusCode -eq 200) {
         Write-Host "Connection Verified!" -ForegroundColor Green
      }

   } 
   catch [System.Net.WebException] {
      $exceptionMessage = $Error[0].Exception
      if ($exceptionMessage -match "503") {
         Write-Host "Server Unavaiable" -ForegroundColor Red
      }
      elseif ($exceptionMessage -match "404") {
         Write-Host "Page Not found" -ForegroundColor Red
      }


   }
}

【讨论】:

    【解决方案6】:

    以下是我用于基本 Web URL 测试的 PowerShell 代码。它包括接受无效证书和获取有关证书检查结果的详细信息的能力。

    $CertificateValidatorClass = @'
    using System;
    using System.Collections.Concurrent;
    using System.Net;
    using System.Security.Cryptography;
    using System.Text;
    
    namespace CertificateValidation
    {
        public class CertificateValidationResult
        {
            public string Subject { get; internal set; }
            public string Thumbprint { get; internal set; }
            public DateTime Expiration { get; internal set; }
            public DateTime ValidationTime { get; internal set; }
            public bool IsValid { get; internal set; }
            public bool Accepted { get; internal set; }
            public string Message { get; internal set; }
    
            public CertificateValidationResult()
            {
                ValidationTime = DateTime.UtcNow;
            }
        }
    
        public static class CertificateValidator
        {
            private static ConcurrentStack<CertificateValidationResult> certificateValidationResults = new ConcurrentStack<CertificateValidationResult>();
    
            public static CertificateValidationResult[] CertificateValidationResults
            {
                get
                {
                    return certificateValidationResults.ToArray();
                }
            }
    
            public static CertificateValidationResult LastCertificateValidationResult
            {
                get
                {
                    CertificateValidationResult lastCertificateValidationResult = null;
                    certificateValidationResults.TryPeek(out lastCertificateValidationResult);
    
                    return lastCertificateValidationResult;
                }
            }
    
            public static bool ServicePointManager_ServerCertificateValidationCallback(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
            {
                StringBuilder certificateValidationMessage = new StringBuilder();
                bool allowCertificate = true;
    
                if (sslPolicyErrors != System.Net.Security.SslPolicyErrors.None)
                {
                    if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch) == System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch)
                    {
                        certificateValidationMessage.AppendFormat("The remote certificate name does not match.\r\n", certificate.Subject);
                    }
    
                    if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) == System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors)
                    {
                        certificateValidationMessage.AppendLine("The certificate chain has the following errors:");
                        foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus chainStatus in chain.ChainStatus)
                        {
                            certificateValidationMessage.AppendFormat("\t{0}", chainStatus.StatusInformation);
    
                            if (chainStatus.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.Revoked)
                            {
                                allowCertificate = false;
                            }
                        }
                    }
    
                    if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable) == System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable)
                    {
                        certificateValidationMessage.AppendLine("The remote certificate was not available.");
                        allowCertificate = false;
                    }
    
                    System.Console.WriteLine();
                }
                else
                {
                    certificateValidationMessage.AppendLine("The remote certificate is valid.");
                }
    
                CertificateValidationResult certificateValidationResult = new CertificateValidationResult
                    {
                        Subject = certificate.Subject,
                        Thumbprint = certificate.GetCertHashString(),
                        Expiration = DateTime.Parse(certificate.GetExpirationDateString()),
                        IsValid = (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None),
                        Accepted = allowCertificate,
                        Message = certificateValidationMessage.ToString()
                    };
    
                certificateValidationResults.Push(certificateValidationResult);
                return allowCertificate;
            }
    
            public static void SetDebugCertificateValidation()
            {
                ServicePointManager.ServerCertificateValidationCallback = ServicePointManager_ServerCertificateValidationCallback;
            }
    
            public static void SetDefaultCertificateValidation()
            {
                ServicePointManager.ServerCertificateValidationCallback = null;
            }
    
            public static void ClearCertificateValidationResults()
            {
                certificateValidationResults.Clear();
            }
        }
    }
    '@
    
    function Set-CertificateValidationMode
    {
        <#
        .SYNOPSIS
        Sets the certificate validation mode.
        .DESCRIPTION
        Set the certificate validation mode to one of three modes with the following behaviors:
            Default -- Performs the .NET default validation of certificates. Certificates are not checked for revocation and will be rejected if invalid.
            CheckRevocationList -- Cerftificate Revocation Lists are checked and certificate will be rejected if revoked or invalid.
            Debug -- Certificate Revocation Lists are checked and revocation will result in rejection. Invalid certificates will be accepted. Certificate validation
                     information is logged and can be retrieved from the certificate handler.
        .EXAMPLE
        Set-CertificateValidationMode Debug
        .PARAMETER Mode
        The mode for certificate validation.
        #>
        [CmdletBinding(SupportsShouldProcess = $false)]
        param
        (
            [Parameter()]
            [ValidateSet('Default', 'CheckRevocationList', 'Debug')]
            [string] $Mode
        )
    
        begin
        {
            $isValidatorClassLoaded = (([System.AppDomain]::CurrentDomain.GetAssemblies() | ?{ $_.GlobalAssemblyCache -eq $false }) | ?{ $_.DefinedTypes.FullName -contains 'CertificateValidation.CertificateValidator' }) -ne $null
    
            if ($isValidatorClassLoaded -eq $false)
            {
                Add-Type -TypeDefinition $CertificateValidatorClass
            }
        }
    
        process
        {
            switch ($Mode)
            {
                'Debug'
                {
                    [System.Net.ServicePointManager]::CheckCertificateRevocationList = $true
                    [CertificateValidation.CertificateValidator]::SetDebugCertificateValidation()
                }
                'CheckRevocationList'
                {
                    [System.Net.ServicePointManager]::CheckCertificateRevocationList = $true
                    [CertificateValidation.CertificateValidator]::SetDefaultCertificateValidation()
                }
                'Default'
                {
                    [System.Net.ServicePointManager]::CheckCertificateRevocationList = $false
                    [CertificateValidation.CertificateValidator]::SetDefaultCertificateValidation()
                }
            }
        }
    }
    
    function Clear-CertificateValidationResults
    {
        <#
        .SYNOPSIS
        Clears the collection of certificate validation results.
        .DESCRIPTION
        Clears the collection of certificate validation results.
        .EXAMPLE
        Get-CertificateValidationResults
        #>
        [CmdletBinding(SupportsShouldProcess = $false)]
        param()
    
        begin
        {
            $isValidatorClassLoaded = (([System.AppDomain]::CurrentDomain.GetAssemblies() | ?{ $_.GlobalAssemblyCache -eq $false }) | ?{ $_.DefinedTypes.FullName -contains 'CertificateValidation.CertificateValidator' }) -ne $null
    
            if ($isValidatorClassLoaded -eq $false)
            {
                Add-Type -TypeDefinition $CertificateValidatorClass
            }
        }
    
        process
        {
            [CertificateValidation.CertificateValidator]::ClearCertificateValidationResults()
            Sleep -Milliseconds 20
        }
    }
    
    function Get-CertificateValidationResults
    {
        <#
        .SYNOPSIS
        Gets the certificate validation results for all operations performed in the PowerShell session since the Debug cerificate validation mode was enabled.
        .DESCRIPTION
        Gets the certificate validation results for all operations performed in the PowerShell session since the Debug certificate validation mode was enabled in reverse chronological order.
        .EXAMPLE
        Get-CertificateValidationResults
        #>
        [CmdletBinding(SupportsShouldProcess = $false)]
        param()
    
        begin
        {
            $isValidatorClassLoaded = (([System.AppDomain]::CurrentDomain.GetAssemblies() | ?{ $_.GlobalAssemblyCache -eq $false }) | ?{ $_.DefinedTypes.FullName -contains 'CertificateValidation.CertificateValidator' }) -ne $null
    
            if ($isValidatorClassLoaded -eq $false)
            {
                Add-Type -TypeDefinition $CertificateValidatorClass
            }
        }
    
        process
        {
            return [CertificateValidation.CertificateValidator]::CertificateValidationResults
        }
    }
    
    function Test-WebUrl
    {
        <#
        .SYNOPSIS
        Tests and reports information about the provided web URL.
        .DESCRIPTION
        Tests a web URL and reports the time taken to get and process the request and response, the HTTP status, and the error message if an error occurred.
        .EXAMPLE
        Test-WebUrl 'http://websitetotest.com/'
        .EXAMPLE
        'https://websitetotest.com/' | Test-WebUrl
        .PARAMETER HostName
        The Hostname to add to the back connection hostnames list.
        .PARAMETER UseDefaultCredentials
        If present the default Windows credential will be used to attempt to authenticate to the URL; otherwise, no credentials will be presented.
        #>
        [CmdletBinding()]
        param
        (
            [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
            [Uri] $Url,
            [Parameter()]
            [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = 'Get',
            [Parameter()]
            [switch] $UseDefaultCredentials
        )
    
        process
        {
            [bool] $succeeded = $false
            [string] $statusCode = $null
            [string] $statusDescription = $null
            [string] $message = $null
            [int] $bytesReceived = 0
            [Timespan] $timeTaken = [Timespan]::Zero 
    
            $timeTaken = Measure-Command `
                {
                    try
                    {
                        [Microsoft.PowerShell.Commands.HtmlWebResponseObject] $response = Invoke-WebRequest -UseDefaultCredentials:$UseDefaultCredentials -Method $Method -Uri $Url
                        $succeeded = $true
                        $statusCode = $response.StatusCode.ToString('D')
                        $statusDescription = $response.StatusDescription
                        $bytesReceived = $response.RawContent.Length
    
                        Write-Verbose "$($Url.ToString()): $($statusCode) $($statusDescription) $($message)"
                    }
                    catch [System.Net.WebException]
                    {
                        $message = $Error[0].Exception.Message
                        [System.Net.HttpWebResponse] $exceptionResponse = $Error[0].Exception.GetBaseException().Response
    
                        if ($exceptionResponse -ne $null)
                        {
                            $statusCode = $exceptionResponse.StatusCode.ToString('D')
                            $statusDescription = $exceptionResponse.StatusDescription
                            $bytesReceived = $exceptionResponse.ContentLength
    
                            if ($statusCode -in '401', '403', '404')
                            {
                                $succeeded = $true
                            }
                        }
                        else
                        {
                            Write-Warning "$($Url.ToString()): $($message)"
                        }
                    }
                }
    
            return [PSCustomObject] @{ Url = $Url; Succeeded = $succeeded; BytesReceived = $bytesReceived; TimeTaken = $timeTaken.TotalMilliseconds; StatusCode = $statusCode; StatusDescription = $statusDescription; Message = $message; }
        }
    }
    
    Set-CertificateValidationMode Debug
    Clear-CertificateValidationResults
    
    Write-Host 'Testing web sites:'
    'https://expired.badssl.com/', 'https://wrong.host.badssl.com/', 'https://self-signed.badssl.com/', 'https://untrusted-root.badssl.com/', 'https://revoked.badssl.com/', 'https://pinning-test.badssl.com/', 'https://sha1-intermediate.badssl.com/' | Test-WebUrl | ft -AutoSize
    
    Write-Host 'Certificate validation results (most recent first):'
    Get-CertificateValidationResults | ft -AutoSize
    

    【讨论】:

      【解决方案7】:

      对于 powershell (7) 核心,这是有效的:

      curl -I gourav.io
      

      输出:

      HTTP/1.1 308 Permanent Redirect
      Date: Tue, 13 Apr 2021 20:29:43 GMT
      Content-Type: text/plain
      Connection: keep-alive
      Location: https://gourav.io/
      Refresh: 0;url=https://gourav.io/
      server: Vercel
      x-vercel-id: bom1::zfh9m-1618345783130-62d01e38e332
      

      或

      Invoke-WebRequest https://gourav.io
      

      输出:

      StatusCode        : 200
      StatusDescription : OK
      Content           : <!DOCTYPE html><html lang="en-US"><head><script async=""
                          src="https://www.googletagmanager.com/gtag/js?id=G-JF3BSQ1LL2"></script><script>
                                      window.dataLayer = window.dataLayer || [];
                                 …
      RawContent        : HTTP/1.1 200 OK
      ...
      ...
      

      【讨论】:

        【解决方案8】:

        我使用它并且工作,(如果链接可用,则返回“Ok”)但如果链接不工作,它会显示错误的红色字母。如何删除此 sn-p 上的错误报告?

        $DownloadLink = "https://www.tightvnc.com/download/2.8.59/tightvnc-2.8.59-gpl-setup-bit.msi"
        

        $NetAvailable = (Invoke-WebRequest -Uri $DownloadLink -UseBasicParsing -DisableKeepAlive -Method Head).StatusDescription

        $NetAvailable = OK

            If ($NetAvailable -eq "OK") {Write-Host "Attempting Download";wget -O "$Destination\$FileName" "$DownloadLink"}
        Else {"";Write-Warning "Could NOT Download, Manually Copy $ProgramName to $Destination BEFORE Proceeding!";"";PAUSE}
        

        但是如果链接不起作用会给我一个错误,然后转到“Else” 它有效,我只想摆脱错误字母。

        【讨论】:

        • 如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。 - From Review
        猜你喜欢
        • 1970-01-01
        • 2017-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多