天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

PHP高級編程實例:編寫守護進程

1.什么是守護進程

守護進程是脫離于終端并且在后臺運行的進程。守護進程脫離于終端是為了避免進程在執(zhí)行過程中的信息在任何終端上顯示并且進程也不會被任何終端所產(chǎn)生的終端信息所打斷。

例如 apache, nginx, mysql 都是守護進程

2.為什么開發(fā)守護進程

很多程序以服務形式存在,他沒有終端或UI交互,它可能采用其他方式與其他程序交互,如TCP/UDP Socket, UNIX Socket, fifo。程序一旦啟動便進入后臺,直到滿足條件他便開始處理任務。

3.何時采用守護進程開發(fā)應用程序

以我當前的需求為例,我需要運行一個程序,然后監(jiān)聽某端口,持續(xù)接受服務端發(fā)起的數(shù)據(jù),然后對數(shù)據(jù)分析處理,再將結果寫入到數(shù)據(jù)庫中; 我采用ZeroMQ實現(xiàn)數(shù)據(jù)收發(fā)。

如果我不采用守護進程方式開發(fā)該程序,程序一旦運行就會占用當前終端窗框,還有受到當前終端鍵盤輸入影響,有可能程序誤退出。

4.守護進程的安全問題

我們希望程序在非超級用戶運行,這樣一旦由于程序出現(xiàn)漏洞被駭客控制,攻擊者只能繼承運行權限,而無法獲得超級用戶權限。

我們希望程序只能運行一個實例,不運行同事開啟兩個以上的程序,因為會出現(xiàn)端口沖突等等問題。

5.怎樣開發(fā)守護進程

例 1. 守護進程例示

<?phpclass ExampleWorker extends Worker { #public function __construct(Logging $logger) { # $this->logger = $logger; #} #protected $logger; protected static $dbh; public function __construct() { } public function run(){  $dbhost = '192.168.2.1';  // 數(shù)據(jù)庫服務器  $dbport = 3306;   $dbuser = 'www';  // 數(shù)據(jù)庫用戶名 $dbpass = 'qwer123';    // 數(shù)據(jù)庫密碼  $dbname = 'example';  // 數(shù)據(jù)庫名  self::$dbh = new PDO("mysql:host=$dbhost;port=$dbport;dbname=$dbname", $dbuser, $dbpass, array(   /* PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES /'UTF8/'', */   PDO::MYSQL_ATTR_COMPRESS => true,   PDO::ATTR_PERSISTENT => true   )  ); } protected function getInstance(){ return self::$dbh;  }}/* the collectable class implements machinery for Pool::collect */class Fee extends Stackable { public function __construct($msg) {  $trades = explode(",", $msg);  $this->data = $trades;  print_r($trades); } public function run() {  #$this->worker->logger->log("%s executing in Thread #%lu", __CLASS__, $this->worker->getThreadId() );  try {   $dbh = $this->worker->getInstance();      $insert = "INSERT INTO fee(ticket, login, volume, `status`) VALUES(:ticket, :login, :volume,'N')";   $sth = $dbh->prepare($insert);   $sth->bindValue(':ticket', $this->data[0]);   $sth->bindValue(':login', $this->data[1]);   $sth->bindValue(':volume', $this->data[2]);   $sth->execute();   $sth = null;      /* ...... */      $update = "UPDATE fee SET `status` = 'Y' WHERE ticket = :ticket and `status` = 'N'";   $sth = $dbh->prepare($update);   $sth->bindValue(':ticket', $this->data[0]);   $sth->execute();   //echo $sth->queryString;   //$dbh = null;  }  catch(PDOException $e) {   $error = sprintf("%s,%s/n", $mobile, $id );   file_put_contents("mobile_error.log", $error, FILE_APPEND);  } }}class Example { /* config */ const LISTEN = "tcp://192.168.2.15:5555"; const MAXCONN = 100; const pidfile = __CLASS__; const uid = 80; const gid = 80;  protected $pool = NULL; protected $zmq = NULL; public function __construct() {  $this->pidfile = '/var/run/'.self::pidfile.'.pid'; } private function daemon(){  if (file_exists($this->pidfile)) {   echo "The file $this->pidfile exists./n";   exit();  }    $pid = pcntl_fork();  if ($pid == -1) {    die('could not fork');  } else if ($pid) {    // we are the parent    //pcntl_wait($status); //Protect against Zombie children   exit($pid);  } else {   // we are the child   file_put_contents($this->pidfile, getmypid());   posix_setuid(self::uid);   posix_setgid(self::gid);   return(getmypid());  } } private function start(){  $pid = $this->daemon();  $this->pool = new Pool(self::MAXCONN, /ExampleWorker::class, []);  $this->zmq = new ZMQSocket(new ZMQContext(), ZMQ::SOCKET_REP);  $this->zmq->bind(self::LISTEN);    /* Loop receiving and echoing back */  while ($message = $this->zmq->recv()) {   //print_r($message);   //if($trades){     $this->pool->submit(new Fee($message));     $this->zmq->send('TRUE');    //}else{   // $this->zmq->send('FALSE');    //}  }  $pool->shutdown();  } private function stop(){  if (file_exists($this->pidfile)) {   $pid = file_get_contents($this->pidfile);   posix_kill($pid, 9);    unlink($this->pidfile);  } } private function help($proc){  printf("%s start | stop | help /n", $proc); } public function main($argv){  if(count($argv) < 2){   printf("please input help parameter/n");   exit();  }  if($argv[1] === 'stop'){   $this->stop();  }else if($argv[1] === 'start'){   $this->start();  }else{   $this->help($argv[0]);  } }}$cgse = new Example();$cgse->main($argv);

5.1. 程序啟動

下面是程序啟動后進入后臺的代碼

通過進程ID文件來判斷,當前進程狀態(tài),如果進程ID文件存在表示程序在運行中,通過代碼file_exists($this->pidfile)實現(xiàn),但而后進程被kill需要手工刪除該文件才能運行

private function daemon(){  if (file_exists($this->pidfile)) {   echo "The file $this->pidfile exists./n";   exit();  }    $pid = pcntl_fork();  if ($pid == -1) {    die('could not fork');  } else if ($pid) {   // we are the parent   //pcntl_wait($status); //Protect against Zombie children   exit($pid);  } else {   // we are the child   file_put_contents($this->pidfile, getmypid());   posix_setuid(self::uid);   posix_setgid(self::gid);   return(getmypid());  } }

程序啟動后,父進程會推出,子進程會在后臺運行,子進程權限從root切換到指定用戶,同時將pid寫入進程ID文件。

5.2. 程序停止

程序停止,只需讀取pid文件,然后調(diào)用posix_kill($pid, 9); 最后將該文件刪除。

private function stop(){  if (file_exists($this->pidfile)) {   $pid = file_get_contents($this->pidfile);   posix_kill($pid, 9);    unlink($this->pidfile);  } }

php技術PHP高級編程實例:編寫守護進程,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 亚洲偷自拍精品视频在线观看 | 老师的快感电影完整版 | 99视频在线免费看 | 蜜臀AV精品一区二区三区 | 日本综艺大尺度无删减版在线 | 久久九九少妇免费看A片 | 99精品小视频 | TUBE69CHINESE学生| 国产在线观看www | 一本之道高清视频在线观看 | 野花香HD免费高清版6高清版 | 91精品专区 | 麻豆国产人妻欲求不满 | 国产欧美一区二区精品仙草咪 | 99视频在线国产 | 色欲人妻无码AV专区 | 久久国产乱子伦免费精品 | 日韩熟女精品一区二区三区 | 亚洲一区二区三区免费看 | 国产原创中文视频 | 亚洲精品在线播放视频 | 久久视频这里只精品99热在线 | 欧美国产在线一区 | 拔擦拔擦8X永久华人免费播放器 | 双性精跪趴灌满h室友4p | 国产精品综合AV一区二区国产馆 | 色哟哟网站入口在线观看视频 | 久久超碰国产精品最新 | 国产精品999| 久久这里只有是精品23 | 日本高清天码一区在线播放 | 动漫美女性侵 | 囯产精品一区二区三区线 | 久久精品电影久久电影大全 | 色姐妹久久综合在线av | 吉吉影音先锋av资源网 | 搡女人免费免费视频观看 | 亚洲精品喷白浆在线观看 | 精品国产乱码久久久久久乱码 | 国产婷婷一区二区在线观看 | 欧美日韩视频高清一区 |