《PHP教程:PHP高级编程实例:编写守护进程》要点:
本文介绍了PHP教程:PHP高级编程实例:编写守护进程,希望对您有用。如果有疑问,可以联系我们。
PHP应用1.什么是守护过程
PHP应用守护进程是脱离于终端而且在后台运行的进程.守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示而且进程也不会被任何终端所产生的终端信息所打断.
PHP应用例如 apache, nginx, mysql 都是守护过程
PHP应用2.为什么开发守护过程
PHP应用很多程序以服务形式存在,他没有终端或UI交互,它可能采纳其他方式与其他程序交互,如TCP/UDP Socket, UNIX Socket, fifo.程序一旦启动便进入后台,直到满足条件他便开始处理任务.
PHP应用3.何时采纳守护进程开发应用程序
PHP应用以我当前的需求为例,我必要运行一个程序,然后监听某端口,持续接受服务端发起的数据,然后对数据分析处理,再将结果写入到数据库中; 我采用ZeroMQ实现数据收发.
PHP应用如果我不采纳守护进程方式开发该程序,程序一旦运行就会占用当前终端窗框,还有受到当前终端键盘输入影响,有可能程序误退出.
PHP应用4.守护进程的平安问题
PHP应用我们希望程序在非超等用户运行,这样一旦由于程序出现漏洞被骇客控制,攻击者只能继承运行权限,而无法获得超等用户权限.
PHP应用我们希望程序只能运行一个实例,不运行同事开启两个以上的程序,因为会呈现端口冲突等等问题.
PHP应用5.怎样开发守护过程
PHP应用例 1. 守护过程例示
PHP应用
<?php
class 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'; // 数据库服务器
$dbport = 3306;
$dbuser = 'www'; // 数据库用户名
$dbpass = 'qwer123'; // 数据库暗码
$dbname = 'example'; // 数据库名
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);
PHP应用5.1. 程序启动
PHP应用下面是法式启动后进入后台的代码
PHP应用通过进程ID文件来判断,当前进程状态,如果进程ID文件存在表示程序在运行中,通过代码file_exists($this->pidfile)实现,但而后进程被kill必要手工删除该文件才能运行
PHP应用
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());
}
}
PHP应用法式启动后,父进程会推出,子进程会在后台运行,子进程权限从root切换到指定用户,同时将pid写入进程ID文件.
PHP应用5.2. 法式停止
PHP应用法式停止,只需读取pid文件,然后调用posix_kill($pid, 9); 最后将该文件删除.
PHP利用
private function stop(){
if (file_exists($this->pidfile)) {
$pid = file_get_contents($this->pidfile);
posix_kill($pid, 9);
unlink($this->pidfile);
}
}
《PHP教程:PHP高级编程实例:编写守护进程》是否对您有启发,欢迎查看更多与《PHP教程:PHP高级编程实例:编写守护进程》相关教程,学精学透。维易PHP学院为您提供精彩教程。