curl和ping - 如何检查网站是处于上线还是下线状态?

36

我想使用PHP检查一个特定时间点网站是正常还是宕机。我了解到curl可以获取文件的内容,但我不需要读取网站的内容,只想检查网站的状态。有没有办法来检查网站的状态?我们可以使用ping来检查吗?对于我来说,从服务器获取状态信号(如404、403等)就足够了。一个小代码片段会对我很有帮助。

我想使用 PHP 检查某个时刻网站的运行状态。我知道 curl 可以获取网页内容,但我并不需要读取网页内容,只需检查网站是否可用。有没有办法检查网站的运行状态?我们可以使用 ping 来检查吗?对我而言,从服务器获取状态码(如 404、403 等)就足够了。希望能提供一小段代码示例。

2
你如何定义“up”?返回HTTP 200的空白页面是“up”吗? - webbiedave
我的定义:up表示可ping的服务器,down表示不可ping的(主机不可达)。 - MaXi32
8个回答

51

应该可以这样做

    $url = 'yoururl';
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_exec($ch);
    $retcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    if (200==$retcode) {
        // All's well
    } else {
        // not so much
    }

2
我也更喜欢将CURLOPT_CONNECTTIMEOUTCURLOPT_TIMEOUT设置为较低的值。 - machineaddict
@machineaddict 你的意思是在等待连接时输出“网站离线”吗?我不明白一件事情检查两次和等待当前操作有什么区别。 - m3nda
即使将CURLOPT_FOLLOWLOCATION设置为true,它仍然返回301返回代码……这怎么可能? - Henry Harris
@HenryHarris:阅读这个这个 - machineaddict
2
有很多比200更成功的HTTP响应代码。https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success - carefulnow1

21
curl -Is $url | grep HTTP | cut -d ' ' -f2

curl -Is $url 命令输出仅为HTTP响应头。

grep HTTP 过滤出HTTP响应头。

cut -d ' ' -f2 将输出裁剪为第二个“单词”,在这种情况下是状态码。

例如:

$ curl -Is google.com | grep HTTP | cut -d ' ' -f2
301

29
在提供解决问题的代码时,最好也至少给出一个简短的说明,以便读者不必逐行分析来理解差异。请注意,说明不应改变原文意思。 - Fluffeh

10
function checkStatus($url) {
    $agent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; pt-pt) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27";

    // initializes curl session
    $ch = curl_init();

    // sets the URL to fetch
    curl_setopt($ch, CURLOPT_URL, $url);

    // sets the content of the User-Agent header
    curl_setopt($ch, CURLOPT_USERAGENT, $agent);

    // make sure you only check the header - taken from the answer above
    curl_setopt($ch, CURLOPT_NOBODY, true);

    // follow "Location: " redirects
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    // return the transfer as a string
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    // disable output verbose information
    curl_setopt($ch, CURLOPT_VERBOSE, false);

    // max number of seconds to allow cURL function to execute
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);

    // execute
    curl_exec($ch);

    // get HTTP response code
    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

    curl_close($ch);

    if ($httpcode >= 200 && $httpcode < 300)
        return true;
    else
        return false;
}
 
// how to use
//===================
if ($this->checkStatus("https://stackoverflow.com"))
    echo "Website is up";
else
    echo "Website is down";
exit;

6

以下是我所采取的方法。我设置了用户代理,以最小化目标封禁我的机会,并且禁用了SSL验证,因为我知道目标:

private static function checkSite( $url ) {
    $useragent = $_SERVER['HTTP_USER_AGENT'];

    $options = array(
            CURLOPT_RETURNTRANSFER => true,      // return web page
            CURLOPT_HEADER         => false,     // do not return headers
            CURLOPT_FOLLOWLOCATION => true,      // follow redirects
            CURLOPT_USERAGENT      => $useragent, // who am i
            CURLOPT_AUTOREFERER    => true,       // set referer on redirect
            CURLOPT_CONNECTTIMEOUT => 2,          // timeout on connect (in seconds)
            CURLOPT_TIMEOUT        => 2,          // timeout on response (in seconds)
            CURLOPT_MAXREDIRS      => 10,         // stop after 10 redirects
            CURLOPT_SSL_VERIFYPEER => false,     // SSL verification not required
            CURLOPT_SSL_VERIFYHOST => false,     // SSL verification not required
    );
    $ch = curl_init( $url );
    curl_setopt_array( $ch, $options );
    curl_exec( $ch );

    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return ($httpcode == 200);
}

5

你是否看过get_headers()函数? http://it.php.net/manual/en/function.get-headers.php。它似乎可以完全满足你的需求。

如果你直接使用curl并加上-I标志,它将返回HTTP头信息(如404),而不是页面HTML。在PHP中,相应的选项是curl_setopt($ch, CURLOPT_NOBODY, 1);


5

Ping 无法达到你所期望的效果 - 它只能告诉你机器是否启动(并响应 Ping)。但这并不意味着 web 服务器正常运行。

你可以尝试使用 http_head 方法 - 它会检索 web 服务器发送回来的头部。如果服务器返回头部,那么你就知道它正在运行。



3

您无法通过ping测试Web服务器,因为它们是不同的服务。服务器可能正在运行,但Web服务器守护进程仍可能崩溃。所以curl就是您的好帮手。只需忽略内容。


0

此函数检查URL是否存在。检查时间最长为300毫秒,但您可以在cURL选项CURLOPT_TIMEOUT_MS中更改该参数。

/*
 * Check is URL exists
 *
 * @param  $url           Some URL
 * @param  $strict        You can add it true to check only HTTP 200 Response code
 *                        or you can add some custom response code like 302, 304 etc.
 *
 * @return boolean true or false
 */
function is_url_exists($url, $strict = false)
{
    if (is_int($strict) && $strict >= 100 && $strict < 600 || is_array($strict)) {
        if(is_array($strict)) {
            $response = $strict;
        } else {
            $response = [$strict];
        }
    } else if ($strict === true || $strict === 1) {
        $response = [200];
    } else {
        $response = [200,202,301,302,303];
    }
    $ch = curl_init( $url );
    
    $options = [
        CURLOPT_NOBODY          => true,
        CURLOPT_FAILONERROR     => true,
        CURLOPT_RETURNTRANSFER  => true,
        CURLOPT_NOSIGNAL        => true,
        CURLOPT_SSL_VERIFYPEER  => false,
        CURLOPT_SSL_VERIFYHOST  => false,
        CURLOPT_HEADER          => false,
        CURLOPT_FOLLOWLOCATION  => true,
        CURLOPT_VERBOSE         => false,
        CURLOPT_USERAGENT       => ( $_SERVER['HTTP_USER_AGENT'] ?? '' ),
        CURLOPT_TIMEOUT_MS      => 300, // TImeout in miliseconds
        CURLOPT_MAXREDIRS       => 2,
    ];
    
    curl_setopt_array($ch, $options);
    
    $return = curl_exec($ch);
    $errno = curl_errno($ch);
    $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    curl_close($ch);
    
    if (!$errno && $return !== false) {
        return ( in_array($httpcode, $response) !== false );
    }
    
    return false;
}

您可以检查任何URL,从域名、IP地址到图像、文件等。我认为这是最快的方式,并且已被证明是有用的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接