CmdSignal.php
3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
/**
* TODO:: 如果想要在终止 任务时不让数据丢失或者异常,请使用此类
* @author:dc
* @time 2023/8/21 11:03
* Class CmdSignal
* @package App\Console\Commands
*/
trait CmdSignal
{
/**
* 是否停止
* @var bool
*/
public $isStop = false;
/**
* 超时未退出,强制退出 暂时未实现
* @var int
*/
public $stopTimeOut = 30;
public $debugLogFile = null;
/**
* 调试输出
* @param $msg
* @author:dc
* @time 2023/8/21 11:22
*/
public function debug_echo($msg){
if($this->debugLogFile){
@file_put_contents($this->debugLogFile,date('Y-m-d H:i:s')." ===> ".print_r($msg,1).PHP_EOL,FILE_APPEND);
}else{
echo date('Y-m-d H:i:s')." ===> ".print_r($msg,1).PHP_EOL;
}
}
/**
* @return bool
*/
public function handle()
{
if($this->isRunning()){
$this->debug_echo('脚本已运行,请无重复运行');
return 1;
}
$this->debug_echo('已启动脚本');
// 启动时
if(method_exists($this,'init')){
$this->init();
}
// 注册信号处理程序
// SIGHUP:终端控制进程时终止或挂起进程
//SIGINT:中断进程(通常由CTRL+C发出)
//SIGQUIT:退出进程并生成核心转储
//SIGILL:非法指令
//SIGABRT:由调试程序触发的异常终止信号
//SIGFPE:浮点异常
//SIGKILL:无条件终止进程
//SIGSEGV:无效的内存引用
//SIGPIPE:写入已关闭的FIFO或套接字时产生的信号
//SIGTERM:要求终止进程的信号
//SIGUSR1:用户定义的信号1
//SIGUSR2:用户定义的信号2
$handler = function ($signal){
// 可以处理其他程序
$this->isStop = true;
};
pcntl_signal(SIGTERM, $handler);
pcntl_signal(SIGINT, $handler);
// pcntl_signal(SIGHUP, $handler);
// 检查是否接收到信号
pcntl_signal_dispatch();
$tryNum = 0;
// 无限循环,模拟进程运行
while (true) {
// 做一些工作... 异常超过5次就重启下进程
if($this->isStop || $tryNum>5){
break;
}
try {
$this->start();
}catch (\Throwable $e){
$tryNum++;
// 保证此程序正常
$this->debug_echo('异常消息:'.$e->getMessage());
$this->debug_echo('异常文件:'.$e->getFile().':'.$e->getLine());
$this->debug_echo($e->getTraceAsString());
}
}
$this->debug_echo('已退出程序');
return Command::SUCCESS;
}
/**
* 获取进程启动名称
* @return mixed
* @throws \Exception
* @author:dc
* @time 2023/8/21 11:43
*/
public function getSignature(){
if(empty($this->signature)){
throw new \Exception('无法获取到启动命令');
}
return $this->signature;
}
/**
* 是否已运行
* @param int $max 最大运行多少进程
* @return bool
* @throws \Exception
* @author:dc
* @time 2023/8/21 11:54
*/
public function isRunning($max=1):bool {
$ps = "ps -ef | grep \"artisan ".$this->getSignature()."\" | grep -v grep | wc -l";
$num = exec($ps);
if(property_exists($this,'maxRunNumber')){
$max = $this->maxRunNumber;
}
if($num>$max){
return true;
}
return false;
}
}