有4台VM虚拟机组成的服务器集群,每个服务器每天都会产生一个标注了日期[date(‘Ymd’)]的日志,我所做的就是通过一个脚本把每个服务器上的日志收集起来,传给Facebook的scribe工具,统一汇集到一台服务器上。代码如下:
<?php
/****/
class CollectLogsCommand extends CConsoleCommand{
public $host='10.1.1.104';
public $port='1464';
private $socket;
private $transport;
private $protocol;
private $scribe_client;
private $transport_opened;
private $serverIP;
//获取服务器IP地址
private function getServerIp($withV6=false){
preg_match_all('/inet'.($withV6 ? '6?' : '').' addr: ?([^ ]+)/', `/sbin/ifconfig`, $ips);
$ip = "";
foreach($ips[1] as $item){
if($item!='127.0.0.1') $ip = $item;
break;
}
return $ip;
}
public function actionLogCollecter(){
if(!$this->serverIP){
$this->serverIP=$this->getServerIp();
}
//从php的标准输入读取
$fp=fopen('php://stdin','r');
while(($input = fgets($fp, 1024*10))!=false){
//删除回车字符
$input=preg_replace("/\s+$/",'',$input);
//加上IP地址
$input=$this->serverIP."\t".$input."\r\n";
$this->readLog($input,'mp.uuzu.com');
}
}
//定时脚本,每天更换所迁移的日志名称
public function actionChangeLog(){
//先杀死昨天的脚本
$yesterday=date('Ymd',strtotime('-1 day'));
shell_exec("ps aux | grep logcollecter |grep -v 'grep' | awk '{print $2}' |xargs kill -9");
//判断日志文件是否存在,不存在就一直处于等待状态
$file="/tmp/php/Appcharge_log_".date('Ymd').".log";
while(!is_file($file)){
sleep(10);
}
//重新开启一个脚本
shell_exec("tail -F /tmp/php/Appcharge_log_".date('Ymd').".log | /usr/local/webserver/php/bin/php /data/web/mp.uuzu.com/protected/yiic.php CollectLogs logcollecter");
}
//把信息传给Scribed
public function readLog($message,$category){
//init
$path=dirname(__FILE__)."/../../../common/logging/phpscribe";
$path=realpath($path);
$GLOBALS['THRIFT_ROOT'] = $path;
require_once $path.'/packages/scribe/scribe.php';
require_once $path.'/transport/TSocket.php';
require_once $path.'/transport/TFramedTransport.php';
require_once $path.'/protocol/TBinaryProtocol.php';
$this->socket = new TSocket($this->host, $this->port);
$this->transport = new TFramedTransport($this->socket);
$this->protocol = new TBinaryProtocol($this->transport, false, false);
$this->scribe_client = new scribeClient($this->protocol, $this->protocol);
$this->transport_opened = FALSE;
//保存
if(FALSE === $this->transport_opened){
@$this->transport_opened = $this->transport->open();
}
//把日志信息搞成数组
$log['category'] = $category;
$log['message'] = $message;
if($this->transport_opened){
$entry = new LogEntry($log);
$messages = array($entry);
try{
$ret = $this->scribe_client->Log($messages);
$ret=var_export($ret,true);
return $ret;
}catch(Exception $e){
echo $e->getMessage();
}
}
}
}
这里面包含了2个脚本LogCollecter收集本机日志,通过Linux命令tail -f 日志文件用管道输出给此脚本,然后脚本里面用PHP的标准输入读取,之后调用readLog(); changelog是负责每天0点关闭之前的logcollecter然后重新开启logcollecter,目的是更换日志文件。 两个方法:getServerIP()负责获取服务器IP地址,实质上就是执行了ifconfig命令之后用正则表达式剥取。因为脚本不通过http请求,是不能通过server_addr获取的,readLog()是把读取到的日志字符串传输给Scribed,Scribed具体用法网上有资料,就不再介绍。
用法:定时任务每天 00:00执行changelog脚本即可。