作者:朱先忠编…
来源:天极
热度:
2006-10-27 16:03:00
摘要:在本文中,让我们共同探讨基于PHP语言构建一个基本的服务器端监视引擎的诸多技巧及注意事项,并给出完整的源码实现。
一. 更改工作目录的问题
当你编写一个监视程序时,让它设置自己的工作目录通常更好些。这样以来,如果你使用一个相对路径读写文件,那么,它会根据情况自动处理用户期望存放文件的位置。总是限制程序中使用的路径尽管是一种良好的实践;但是,却失去了应有的灵活性。因此,改变你的工作目录的最安全的方法是,既使用chdir()也使用chroot()。
chroot()可用于PHP的CLI和CGI版本中,但是却要求程序以根权限运行。chroot()实际上把当前进程的路径从根目录改变到指定的目录。这使得当前进程只能执行存在于该目录下的文件。经常情况下,chroot()由服务器作为一个"安全设备"使用以确保恶意代码不会修改一个特定的目录之外的文件。请牢记,尽管chroot()能够阻止你访问你的新目录之外的任何文件,但是,任何当前打开的文件资源仍然能够被存取。例如,下列代码能够打开一个日志文件,调用chroot()并切换到一个数据目录;然后,仍然能够成功地登录并进而打开文件资源:
| <?php $logfile = fopen("/var/log/chroot.log", "w"); chroot("/Users/george"); fputs($logfile, "Hello From Inside The Chroot\n"); ?> |
| $pw=posix_getpwnam('nobody'); posix_setuid($pw['uid']); posix_setgid($pw['gid']); |
| $fp=fopen("/tmp/.lockfile","a"); if(!$fp || !flock($fp, LOCK_EX | LOCK_NB)) { fputs(STDERR, "Failed to acquire lock\n"); exit; } /*成功锁定以安全地执行工作*/ |
注意,有关锁机制的讨论涉及较多内容,在此不多加解释。
四. 构建监视服务
在这一节中,我们将使用PHP来编写一个基本的监视引擎。因为你不会事先知道怎样改变,所以你应该使它的实现既灵活又具可能性。
该记录程序应该能够支持任意的服务检查(例如,HTTP和FTP服务)并且能够以任意方式(通过电子邮件,输出到一个日志文件,等等)记录事件。你当然想让它以一个守护程序方式运行;所以,你应该请求它输出其完整的当前状态。
一个服务需要实现下列抽象类:
| abstract class ServiceCheck { const FAILURE = 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($params); public function __call($name, $args) { if(isset($this->$name)) { return $this->$name; } } public function set_next_attempt() { $this->next_attempt = time() + $this->frequency; } public abstract function run(); public function post_run($status) { if($status !== $this->current_status) { $this->previous_status = $this->current_status; } if($status === self::FAILURE) { if( $this->current_status === self::FAILURE ) { $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($this->loggers as $logger) { $logger->log_current_status($this); } } private function log_service_event() { foreach($this->loggers as $logger) { $logger->log_service_event($this); } } public function register_logger(ServiceLogger $logger) { $this->loggers[] = $logger; } } |
我来说两句:
推荐文章
相关文章