php源码中powerby,高阶篇一 TP5命令行之守护任务源码

# 高阶篇一 TP5命令行之守护任务源码

> 本方法使用了多线程 执行时候使用了子线程

此方法使用的实例参见 高阶篇二 使用Redis队列发送微信模版消息

https://www.kancloud.cn/mikkle/thinkphp5_study/396284

~~~

namespace app\base\command;

use app\base\controller\Redis;

use think\Config;

use think\console\Command;

use think\console\Input;

use think\console\Output;

use think\Exception;

use think\Log;

/**

* Created by PhpStorm.

* Power by Mikkle

* QQ:776329498

* Date: 2017/6/12

* Time: 15:07

*/

class Mikkle extends Command

{

protected $sleep = 3;

protected $redis;

protected $listName;

protected $pcntl;

public function __construct($name= null)

{

parent::__construct($name);

$this->redis=Redis::instance(Config::get("command.redis"));

$this->listName = "worker_list";

$this->pcntl =true;

}

protected function configure()

{

$this->setName('mikkle')->setDescription('Here is the mikkle\'s command ');

}

protected function execute(Input $input, Output $output)

{

while(true){

//标记后端服务运行中

$this->signWorking();

echo "==================================================".PHP_EOL;

$this->autoClass();

echo "==================================================".PHP_EOL;

$this->sleep();

}

}

/**

* 自动执行

* Power: Mikkle

* Email:776329498@qq.com

* @return bool

*/

protected function autoClass()

{

$works = $this->getWorks();

if ($works) {

foreach ($works as $item => $work) {

if ($this->pcntl) {

$this->pcntlWorker($work, $item);

} else {

$this->runWorker($work, $item);

}

}

} else {

return false;

}

}

public function getWorks(){

try{

return $this->redis->hget($this->listName);

}catch (Exception $e){

return false;

}

}

/**

* 检测执行方法是否存在

* Power: Mikkle

* Email:776329498@qq.com

* @param $work

* @param $item

* @return bool

*/

protected function checkWorkerExists($work,$item){

if (class_exists($work)){

if(method_exists($work,'run')){

return true;

}else{

return false;

}

}

}

/**

* 运行任务

* Power: Mikkle

* Email:776329498@qq.com

* @param $work

* @param $item

*/

protected function runWorker($work,$item){

try{

if($this->checkWorkerExists($work, $item)) {

echo "执行[{$work}]任务" . PHP_EOL;

$work::run();

Log::notice("执行[{$work}]任务");

}else{

echo "执行[{$work}]任务的run方法不存在".PHP_EOL;

$this->redis->hdel($this->listName,$item);

}

}catch (Exception $e){

echo "执行[{$work}]任务失败" . PHP_EOL;

Log::notice($e->getMessage());

if ($this->pcntl) {

$this->pcntlKill();

}

}

}

/**

* 分进程

* Power: Mikkle

* Email:776329498@qq.com

* @param $work

* @param $item

*/

protected function pcntlWorker($work,$item)

{

try{

// 通过pcntl得到一个子进程的PID

$pid = pcntl_fork();

if ($pid == -1) {

// 错误处理:创建子进程失败时返回-1.

die ('could not fork');

} else if ($pid) {

// 父进程逻辑

// 等待子进程中断,防止子进程成为僵尸进程。

// WNOHANG为非阻塞进程,具体请查阅pcntl_wait PHP官方文档

pcntl_wait($status, WNOHANG);

} else {

// 子进程逻辑

$pid_2 = pcntl_fork();

if ($pid_2 == -1) {

// 错误处理:创建子进程失败时返回-1.

die ('could not fork');

} else if ($pid_2) {

// 父进程逻辑

echo "父进程逻辑开始" . PHP_EOL;

// 等待子进程中断,防止子进程成为僵尸进程。

// WNOHANG为非阻塞进程,具体请查阅pcntl_wait PHP官方文档

pcntl_wait($status, WNOHANG);

echo "父进程逻辑结束" . PHP_EOL;

} else {

// 子进程逻辑

echo "子进程逻辑开始" . PHP_EOL;

$this->runWorker($work,$item);

echo "子进程逻辑结束" . PHP_EOL;

$this->pcntlKill();

}

$this->pcntlKill();

}

}catch (Exception $e){

Log::error($e->getMessage());

}

}

/**

* Kill子进程

* Power: Mikkle

* Email:776329498@qq.com

*/

protected function pcntlKill(){

// 为避免僵尸进程,当子进程结束后,手动杀死进程

if (function_exists("posix_kill")) {

posix_kill(getmypid(), SIGTERM);

} else {

system('kill -9' . getmypid());

}

exit ();

}

public function signWorking(){

$this->redis->set("command","true");

$this->redis->setExpire("command",10);

}

public function sleep($second=""){

$second = $second ? $second : $this->sleep;

// echo "开始睡眠{$second}秒!当前时间:" . date('h:i:s') . PHP_EOL;

sleep(sleep($second)); //TP5的命令行 sleep($second) 不生效

echo "睡眠{$second}秒成功!当前时间:" . date('h:i:s') . PHP_EOL;

}

/**

* @return int

*/

public function getSleep()

{

return $this->sleep;

}

/**

* @param int $sleep

* @return void

*/

public function setSleep($sleep)

{

$this->sleep = $sleep;

}

}

~~~

本源码应用到以下基础内容

TP5实战源码 — 命令行

https://www.kancloud.cn/mikkle/thinkphp5_study/376459

TP5实战源码 — 通过shell建立PHP守护程序

https://www.kancloud.cn/mikkle/thinkphp5_study/376460

感谢大家关注 交流请加QQ群 321449759

![](https://box.kancloud.cn/3499008a08e64306c68873288092a057_286x340.png)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值