情况:我在基于PHP的监控Web应用程序上改进了一些代码,用于检查其他Web应用程序/服务的运行状况。
目标:我们使用CURL作为获取标头的主要方法,以确保通过HTTP返回代码访问受监控的应用程序。这在目前很有用。但是,我们正在尝试构建一个“后备”方法,其中来自受监视应用程序的CURL HTTP代码响应在我们定义的变量之外(即http代码404),PHP将使用类似PING的函数来检查是否在同一地址有任何响应(例如,webserver仍在“运行”(占用给定端口)但不提供正确的标头)。
问题:我们的回退方法(stream_socket_client)适用于非安全站点,因为我们可以简单地定义“主机名:端口”,它可以使用两个curl和stream_socket_client。但是,如果我们要监视安全站点(HTTPS),curl需要在主机之前定义HTTPS协议 - 这将使我们的回退方法(stream_socket_client)功能失败,因为它只使用host:port格式。
所以,例如:
$ URL:https://example.com:443(这会转换为“GOOD”CURL响应,但是转换为stream_socket_client响应)
$ URL:example.com:443(这将返回“UP”stream_socket_client响应,但是“DOWN”CURL响应)
因此,如果我们使用https://example.com:443作为我们的URL,并且Web服务器变得没有响应,但仍在该端口上运行,则两者都会失败,因为HTTPs已定义。
这是我们当前代码的简化版本:
<?php
$url = "example.com:80";
function curl($url) {
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($handle, CURLOPT_HEADER, true);
curl_setopt($handle, CURLOPT_NOBODY, true);
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($handle, CURLOPT_URL, $url);
$response = curl_exec($handle);
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode >= 200 && $httpCode < 400 || $httpCode == 401 || $httpCode == 405) {
echo "CURL GOOD, $httpCode";
echo "STATUS: GREEN";
}
else {
$fp = stream_socket_client("$url", $errno, $errstr);
if (!$fp) {
echo "CURL BAD, PING DOWN";
echo "STATUS: RED";
}
else {
echo "CURL BAD PING UP";
echo "STATUS: YELLOW";
}
}
curl_close($handle);
};
?>
任何想法如何使用回退方法来检查端口是否打开?我不必坚持使用PHP,可以使用一些JS,但更喜欢PHP。
编辑1:
感谢@ drew010,我知道我最终需要使用fsockopen。但是,我需要使用parse_url(),然后可以将“无效”URL传递给fsockopen以进行后备“ping”检查。
但是,我不确定如何仅剥离协议并离开端口和子路径(如果已定义)。我也不确定如何将无菌URL传递给fsockeopn函数以用于检查。到目前为止,我有下面的代码,但我知道我错过了一些代码。
下面的代码将http://example.com
解析为example.com
。
function parseurl($url) {
$url = 'http://example.com:80';
$host = parse_url($url, PHP_URL_HOST);
//this works for stripping protocol and "wwww" but need to leave port and sub path if defined.
if (!$host)
$host = $url;
if (substr($host, 0, 4) == "www.")
$host = substr($host, 4);
if (strlen($host) > 50)
$host = substr($host, 0, 47) . '...';
return $host;
}
// How to pass steril URL to PING function??
function ping($host, $timeout = 1) {
if (!fsockopen($host, $port, $errno, $errstr, $timeout)) {
return false;
echo "OPEN";
}
else {
echo "CLOSED";
}
}
找到答案:
此脚本使用CURL检查给定的HOST是否正在为网页提供服务。如果不是,请使用PING函数检查是否有任何内容在侦听给定端口。
<?php
* This script uses CURL to check if given HOST is serving a webpage.
* If NOT, use a PING function to check if anything is listening on given port.
//* URL MUST contain a PORT after HOST
//* URL CAN include any protocol or sub-path
// sanitizes URL to host:port:path ONLY. (if PORT, PATH don't exist, it is ignored):
function url_to_domain($url) {
$url = 'http://google.com:80';
echo "Input URL ..... $url<br />\n";
$host = parse_url($url, PHP_URL_HOST);
$port = parse_url($url, PHP_URL_PORT);
$path = parse_url($url, PHP_URL_PATH);
// If the URL can't be parsed, use the original URL
// Change to "return false" if you don't want that
if (!$host)
echo "fail";
// $host = $url;
// remove "http/s" and "www" :
if (substr($host, 0, 4) == "www.")
$host = substr($host, 4);
if (strlen($host) > 50)
$host = substr($host, 0, 47) . '...';
// contruct sanitized URL, add ":port/path" to HOST:
return $host . ":" . $port . $path;
}
// pings "sanitized" URL:
$url = (url_to_domain($url));
$fp = pfsockopen($url, $errno, $errstr, $timeout = 5);
if (!$fp) {
echo "Ping URL ...... $url <br />\n ";
echo "URL status ..... CLOSED <br />\n";
echo "Error ............... $errstr ($errno)<br />\n";
}
else {
// $out = "GET / HTTP/1.1\r\n";
// $out .= "$url\r\n";
// $out .= "Connection: Close\r\n\r\n";
//fwrite ($fp, $out);
//displays header:
/*
while (!feof($fp)) {
echo fgets($fp, 128);
}
*/
// fclose($fp);
echo "Ping URL ...... $url <br />\n ";
echo "URL status .... OPEN";
}
?>