用PHP构建一个简单的监视引擎

2021-06-20 作者:未知   |   浏览(

  1、 更改工作目录的问题

  当你撰写一个监视程序时,让它设置我们的工作目录一般更好些。如此以来,假如你用一个相对路径读写文件,那样,它会依据状况自动处置用户期望存放文件的地方。一直限制程序中用的路径尽管是一种好的实践;但,却失去了应有些灵活性。因此,改变你的工作目录的最安全的办法是,既用chdir也用chroot。

  chroot可用于PHP的CLI和CGI版本中,但却需要程序以根权限运行。chroot事实上把目前进程的路径从根目录改变到指定的目录。这使得目前进程只能实行存在于该目录下的文件。常常状况下,chroot由服务器作为一个"安全设施"用以确保恶意代码不会修改一个特定的目录以外的文件。请牢记,尽管chroot可以阻止你访问你的新目录以外的任何文件,但,任何目前打开的文件资源仍然可以被存取。比如,下列代码可以打开一个日志文件,调用chroot并切换到一个数据目录;然后,仍然可以成功地登录并进而打开文件资源:

<?php

$logfile = fopen;

chroot;

fputs;

?>

  假如一个应用程序不可以用chroot,那样你可以调用chdir来设置工作目录。比如,当代码需要加载特定的代码(这部分代码可以在系统的任何地方被定位时),这是非常有用的。注意,chdir没提供安全机制来预防打开未授权的文件。

  · descrih3tion-服务描述。

  · consecutive_failures-自从上次成功以来,服务检查连续失败的次数。

  · status_time-服务被检查的最后时间。

  · failure_time-假如状况为F人工智能LED,则它代表发生失败的时间。

  这个类还达成了察看者模式,允许ServiceLogger种类的对象注册自己,然后当调用log_current_status或log_service_event时调用它。

  这里达成的重要函数是run,它负责概念应该如何实行检查。假如检查成功,它应该返回SUCCESS;不然返回F人工智能LURE。

  4、 构建监视服务

  在这一节中,大家将用PHP来撰写一个基本的监视引擎。由于你不会事先知晓如何改变,所以你应该使它的达成既灵活又具可能性。

该记录程序应该可以支持任意的服务检查并且可以以任意方法记录事件。你当然想让它以一个守护程序方法运行;所以,你应该请求它输出其完整的目前状况。

  一个服务需要达成下列抽象类:

abstract class ServiceCheck {

  · h3revious_status-目前状况之前的状况。

  · frequency-每隔多长期检查一次服务。

  3、 保证排它性

  你可能常常想达成:一个脚本在任何时刻仅运行一个实例。为了保护脚本,这是特别要紧的,由于在后台运行容易致使偶然状况下调用多个实例。

  保证这种排它性的规范技术是,通过用flock来让脚本锁定一个特定的文件。假如锁定失败,该脚本应该输出一个错误并退出。下面是一个示例:

$fp=fopen;

if) {

 fputs;

 exit;

}

/*成功锁定以安全地实行工作*/

  注意,有关锁机制的讨论涉及较多内容,在此不多加讲解。

 const F人工智能LURE = 0;

 const SUCCESS = 1;

 protected $timeout = 30;

 protected $next_attempt;

 protected $current_status = ServiceCheck::SUCCESS;

 protected $previous_status = ServiceCheck::SUCCESS;

 protected $frequency = 30;

 protected $description;

 protected $consecutive_failures = 0;

 protected $status_time;

 protected $failure_time;

 protected $loggers = array;

 abstract public function __construct;

 public function __call

 {

  if) {

   return $this->$name;

  }

 }

 public function set_next_attempt

 {

  $this->next_attempt = time + $this->frequency;

 }

 public abstract function run;

 public function post_run

 {

  if {

   $this->previous_status = $this->current_status;

  }

  if {

   if {

    $this->consecutive_failures++;

   }

   else {

    $this->failure_time = time;

   }

  }

  else {

   $this->consecutive_failures = 0;

  }

  $this->status_time = time;

  $this->current_status = $status;

  $this->log_service_event;

 }

 public function log_current_status

 {

  foreach {

   $logger->log_current_status;

  }

 }

 private function log_service_event

 {

  foreach {

   $logger->log_service_event;

  }

 }

 public function register_logger

 {

  $this->loggers[] = $logger;

 }

}

上面的__call重载办法提供对一个ServiceCheck对象的参数的只读存取操作:

  · timeout-在引擎终止检查之前,这一检查可以挂起多长期。

  · next_attempt-下次尝试连接到服务器的时间。

  · current_status-服务的目前状况:SUCCESS或F人工智能LURE。

  2、 放弃特权

  当撰写Unix守护程序时,一种经典的安全预防手段是让它们放弃所有无需的特权;不然,拥有无需的特权容易招致非必须的麻烦。在代码中含有漏洞的状况下,通过确保一个守护程序以最小权限用户身份运行,总是可以使损失减到最小。

  一种达成此目的的办法是,以非特权用户身份实行该守护程序。然而,假如程序需要在刚开始就打开非特权用户无权打开的资源的话,这一般是不够的。

  假如你以根用户身份运行,那样你可以借用于posix_setuid和posiz_setgid函数来放弃你的特权。下面的示例把目前运行程序的特权改变为用户nobody所拥有些那些权限:

$pw=posix_getpwnam;

posix_setuid;

posix_setgid;

  就象chroot一样,任何在放弃特权之前被打开的特权资源都会维持为打开,但不可以创建新的资源。