我的位置: 首頁 > 學(xué)習(xí)專區(qū) > PHP技術(shù) > 用PHP構(gòu)建一個簡易監(jiān)視引擎

用PHP構(gòu)建一個簡易監(jiān)視引擎

2013-05-06 08:45:15
來源:
[導(dǎo)讀] 一 更改工作目錄的問題當(dāng)你編寫一個監(jiān)視程序時,讓它設(shè)置自己的工作目錄通常更好些。這樣以來,如果你使用一個相對路徑讀寫文件,那么,
一. 更改工作目錄的問題

當(dāng)你編寫一個監(jiān)視程序時,讓它設(shè)置自己的工作目錄通常更好些。這樣以來,如果你使用一個相對路徑讀寫文件,那么,它會根據(jù)情況自動處理用戶期望存放文件的位置。總是限制程序中使用的路徑盡管是一種良好的實踐;但是,卻失去了應(yīng)有的靈活性。因此,改變你的工作目錄的最安全的方法是,既使用chdir()也使用chroot()。

chroot()可用于PHP的CLI和CGI版本中,但是卻要求程序以根權(quán)限運行。chroot()實際上把當(dāng)前進(jìn)程的路徑從根目錄改變到指定的目錄。這使得當(dāng)前進(jìn)程只能執(zhí)行存在于該目錄下的文件。經(jīng)常情況下,chroot()由服務(wù)器作為一個"安全設(shè)備"使用以確保惡意代碼不會修改一個特定的目錄之外的文件。請牢記,盡管chroot()能夠阻止你訪問你的新目錄之外的任何文件,但是,任何當(dāng)前打開的文件資源仍然能夠被存取。例如,下列代碼能夠打開一個日志文件,調(diào)用chroot()并切換到一個數(shù)據(jù)目錄;然后,仍然能夠成功地登錄并進(jìn)而打開文件資源:

$logfile = fopen("/var/log/chroot.log", "w");

chroot("/Users/george");

fputs($logfile, "Hello From Inside The Chroot ");

?>

如果一個應(yīng)用程序不能使用chroot(),那么你可以調(diào)用chdir()來設(shè)置工作目錄。例如,當(dāng)代碼需要加載特定的代碼(這些代碼能夠在系統(tǒng)的任何地方被定位時),這是很有用的。注意,chdir()沒有提供安全機制來防止打開未授權(quán)的文件。

二. 放棄特權(quán)

當(dāng)編寫Unix守護(hù)程序時,一種經(jīng)典的安全預(yù)防措施是讓它們放棄所有不需要的特權(quán);否則,擁有不需要的特權(quán)容易招致不必要的麻煩。在代碼(或PHP本身)中含有漏洞的情況下,通過確保一個守護(hù)程序以最小權(quán)限用戶身份運行,往往能夠使損失減到最小。

一種實現(xiàn)此目的的方法是,以非特權(quán)用戶身份執(zhí)行該守護(hù)程序。然而,如果程序需要在一開始就打開非特權(quán)用戶無權(quán)打開的資源(例如日志文件,數(shù)據(jù)文件,套接字,等等)的話,這通常是不夠的。

如果你以根用戶身份運行,那么你能夠借助于posix_setuid()和posiz_setgid()函數(shù)來放棄你的特權(quán)。下面的示例把當(dāng)前運行程序的特權(quán)改變?yōu)橛脩鬾obody所擁有的那些權(quán)限:

$pw=posix_getpwnam('nobody');

posix_setuid($pw['uid']);

posix_setgid($pw['gid']);

就象chroot()一樣,任何在放棄特權(quán)之前被打開的特權(quán)資源都會保持為打開,但是不能創(chuàng)建新的資源。

三. 保證排它性

你可能經(jīng)常想實現(xiàn):一個腳本在任何時刻僅運行一個實例。為了保護(hù)腳本,這是特別重要的,因為在后臺運行容易導(dǎo)致偶然情況下調(diào)用多個實例。

保證這種排它性的標(biāo)準(zhǔn)技術(shù)是,通過使用flock()來讓腳本鎖定一個特定的文件(經(jīng)常是一個加鎖文件,并且被排它式使用)。如果鎖定失敗,該腳本應(yīng)該輸出一個錯誤并退出。下面是一個示例:

$fp=fopen("/tmp/.lockfile","a");

if(!$fp || !flock($fp, LOCK_EX | LOCK_NB)) {

fputs(STDERR, "Failed to acquire lock ");

exit;

}

/*成功鎖定以安全地執(zhí)行工作*/

注意,有關(guān)鎖機制的討論涉及較多內(nèi)容,在此不多加解釋。

四. 構(gòu)建監(jiān)視服務(wù)

在這一節(jié)中,我們將使用PHP來編寫一個基本的監(jiān)視引擎。因為你不會事先知道怎樣改變,所以你應(yīng)該使它的實現(xiàn)既靈活又具可能性。

該記錄程序應(yīng)該能夠支持任意的服務(wù)檢查(例如,HTTP和FTP服務(wù))并且能夠以任意方式(通過電子郵件,輸出到一個日志文件,等等)記錄事件。你當(dāng)然想讓它以一個守護(hù)程序方式運行;所以,你應(yīng)該請求它輸出其完整的當(dāng)前狀態(tài)。

一個服務(wù)需要實現(xiàn)下列抽象類:

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;

}

}

上面的__call()重載方法提供對一個ServiceCheck對象的參數(shù)的只讀存取操作:

· timeout-在引擎終止檢查之前,這一檢查能夠掛起多長時間。

· next_attempt-下次嘗試連接到服務(wù)器的時間。

· current_status-服務(wù)的當(dāng)前狀態(tài):SUCCESS或FAILURE。

· previous_status-當(dāng)前狀態(tài)之前的狀態(tài)。

· frequency-每隔多長時間檢查一次服務(wù)。

· description-服務(wù)描述。

· consecutive_failures-自從上次成功以來,服務(wù)檢查連續(xù)失敗的次數(shù)。

· status_time-服務(wù)被檢查的最后時間。

· failure_time-如果狀態(tài)為FAILED,則它代表發(fā)生失敗的時間。

這個類還實現(xiàn)了觀察者模式,允許ServiceLogger類型的對象注冊自身,然后當(dāng)調(diào)用log_current_status()或log_service_event()時調(diào)用它。

這里實現(xiàn)的關(guān)鍵函數(shù)是run(),它負(fù)責(zé)定義應(yīng)該怎樣執(zhí)行檢查。如果檢查成功,它應(yīng)該返回SUCCESS;否則返回FAILURE。

深圳北大青鳥嘉華校區(qū)

評論
熱點專題
>>
相關(guān)文章推薦
>>
好吊妞免费视频在线观看,久久亚洲国产人成综合网,久久精品国产2020,欧美精品综合在线
日本免费性色密月AⅤ | 婷婷色五月另类综合 | 亚洲不卡AV影片在线播放 | 亚洲欧美另类综合日韩 | 亚洲乱码中文字幕手机在线 | 色婷婷综合缴情综e |