Task.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <?php
  2. namespace easyTask;
  3. use \Closure as Closure;
  4. use easyTask\Process\Linux;
  5. use easyTask\Process\Win;
  6. use \ReflectionClass as ReflectionClass;
  7. use \ReflectionMethod as ReflectionMethod;
  8. use \ReflectionException as ReflectionException;
  9. /**
  10. * Class Task
  11. * @package easyTask
  12. */
  13. class Task
  14. {
  15. /**
  16. * 任务列表
  17. * @var array
  18. */
  19. private $taskList = [];
  20. /**
  21. * 构造函数
  22. */
  23. public function __construct()
  24. {
  25. //检查运行环境
  26. $currentOs = Helper::isWin() ? 1 : 2;
  27. Check::analysis($currentOs);
  28. $this->initialise($currentOs);
  29. }
  30. /**
  31. * 进程初始化
  32. * @param int $currentOs
  33. */
  34. private function initialise($currentOs)
  35. {
  36. //初始化基础配置
  37. Env::set('prefix', 'Task');
  38. Env::set('canEvent', Helper::canUseEvent());
  39. Env::set('currentOs', $currentOs);
  40. Env::set('canAsync', Helper::canUseAsyncSignal());
  41. Env::set('closeErrorRegister', false);
  42. //初始化PHP_BIN|CODE_PAGE
  43. if ($currentOs == 1) {
  44. Helper::setPhpPath();
  45. Helper::setCodePage();
  46. }
  47. }
  48. /**
  49. * 设置是否守护进程
  50. * @param bool $daemon
  51. * @return $this
  52. */
  53. public function setDaemon($daemon = false)
  54. {
  55. Env::set('daemon', $daemon);
  56. return $this;
  57. }
  58. /**
  59. * 设置任务前缀
  60. * @param string $prefix
  61. * @return $this
  62. */
  63. public function setPrefix($prefix = 'Task')
  64. {
  65. if (Env::get('runTimePath')) {
  66. Helper::showSysError('should use setPrefix before setRunTimePath');
  67. }
  68. Env::set('prefix', $prefix);
  69. return $this;
  70. }
  71. /**
  72. * 设置PHP执行路径(windows)
  73. * @param string $path
  74. * @return $this
  75. */
  76. public function setPhpPath($path)
  77. {
  78. $file = realpath($path);
  79. if (!file_exists($file)) {
  80. Helper::showSysError("the path {$path} is not exists");
  81. }
  82. Helper::setPhpPath($path);
  83. return $this;
  84. }
  85. /**
  86. * 设置时区
  87. * @param string $timeIdent
  88. * @return $this
  89. */
  90. public function setTimeZone($timeIdent)
  91. {
  92. date_default_timezone_set($timeIdent);
  93. return $this;
  94. }
  95. /**
  96. * 设置运行时目录
  97. * @param string $path
  98. * @return $this
  99. */
  100. public function setRunTimePath($path)
  101. {
  102. if (!is_dir($path)) {
  103. Helper::showSysError("the path {$path} is not exist");
  104. }
  105. if (!is_writable($path)) {
  106. Helper::showSysError("the path {$path} is not writeable");
  107. }
  108. Env::set('runTimePath', realpath($path));
  109. return $this;
  110. }
  111. /**
  112. * 设置子进程自动恢复
  113. * @param bool $isRec
  114. * @return $this
  115. */
  116. public function setAutoRecover($isRec = false)
  117. {
  118. Env::set('canAutoRec', $isRec);
  119. return $this;
  120. }
  121. /**
  122. * 设置关闭标准输出的日志
  123. * @param bool $close
  124. * @return $this
  125. */
  126. public function setCloseStdOutLog($close = false)
  127. {
  128. Env::set('closeStdOutLog', $close);
  129. return $this;
  130. }
  131. /**
  132. * 设置关闭系统异常注册
  133. * @param bool $isReg 是否关闭
  134. * @return $this
  135. */
  136. public function setCloseErrorRegister($isReg = false)
  137. {
  138. Env::set('closeErrorRegister', $isReg);
  139. return $this;
  140. }
  141. /**
  142. * 异常通知
  143. * @param string|Closure $notify
  144. * @return $this
  145. */
  146. public function setErrorRegisterNotify($notify)
  147. {
  148. if (Env::get('closeErrorRegister')) {
  149. Helper::showSysError('you must set closeErrorRegister as false before use this api');
  150. }
  151. if (!$notify instanceof Closure && !is_string($notify)) {
  152. Helper::showSysError('notify parameter can only be string or closure');
  153. }
  154. Env::set('notifyHand', $notify);
  155. return $this;
  156. }
  157. /**
  158. * 新增匿名函数作为任务
  159. * @param Closure $func 匿名函数
  160. * @param string $alas 任务别名
  161. * @param mixed $time 定时器间隔
  162. * @param int $used 定时器占用进程数
  163. * @return $this
  164. * @throws
  165. */
  166. public function addFunc($func, $alas, $time = 1, $used = 1)
  167. {
  168. $uniqueId = md5($alas);
  169. if (!($func instanceof Closure)) {
  170. Helper::showSysError('func must instanceof Closure');
  171. }
  172. if (isset($this->taskList[$uniqueId])) {
  173. Helper::showSysError("task $alas already exists");
  174. }
  175. Helper::checkTaskTime($time);
  176. $this->taskList[$uniqueId] = [
  177. 'type' => 1,
  178. 'func' => $func,
  179. 'alas' => $alas,
  180. 'time' => $time,
  181. 'used' => $used
  182. ];
  183. return $this;
  184. }
  185. /**
  186. * 新增类作为任务
  187. * @param string $class 类名称
  188. * @param string $func 方法名称
  189. * @param string $alas 任务别名
  190. * @param mixed $time 定时器间隔
  191. * @param int $used 定时器占用进程数
  192. * @return $this
  193. * @throws
  194. */
  195. public function addClass($class, $func, $alas, $time = 1, $used = 1)
  196. {
  197. $uniqueId = md5($alas);
  198. if (!class_exists($class)) {
  199. Helper::showSysError("class {$class} is not exist");
  200. }
  201. if (isset($this->taskList[$uniqueId])) {
  202. Helper::showSysError("task $alas already exists");
  203. }
  204. try {
  205. $reflect = new ReflectionClass($class);
  206. if (!$reflect->hasMethod($func)) {
  207. Helper::showSysError("class {$class}'s func {$func} is not exist");
  208. }
  209. $method = new ReflectionMethod($class, $func);
  210. if (!$method->isPublic()) {
  211. Helper::showSysError("class {$class}'s func {$func} must public");
  212. }
  213. Helper::checkTaskTime($time);
  214. $this->taskList[$uniqueId] = [
  215. 'type' => $method->isStatic() ? 2 : 3,
  216. 'func' => $func,
  217. 'alas' => $alas,
  218. 'time' => $time,
  219. 'used' => $used,
  220. 'class' => $class
  221. ];
  222. } catch (ReflectionException $exception) {
  223. Helper::showException($exception);
  224. }
  225. return $this;
  226. }
  227. /**
  228. * 新增指令作为任务
  229. * @param string $command 指令
  230. * @param string $alas 任务别名
  231. * @param mixed $time 定时器间隔
  232. * @param int $used 定时器占用进程数
  233. * @return $this
  234. */
  235. public function addCommand($command, $alas, $time = 1, $used = 1)
  236. {
  237. $uniqueId = md5($alas);
  238. if (!Helper::canUseExcCommand()) {
  239. Helper::showSysError('please open the disabled function of shell_exec');
  240. }
  241. if (isset($this->taskList[$uniqueId])) {
  242. Helper::showSysError("task $alas already exists");
  243. }
  244. Helper::checkTaskTime($time);
  245. $this->taskList[$uniqueId] = [
  246. 'type' => 4,
  247. 'alas' => $alas,
  248. 'time' => $time,
  249. 'used' => $used,
  250. 'command' => $command,
  251. ];
  252. return $this;
  253. }
  254. /**
  255. * 获取进程管理实例
  256. * @return Win | Linux
  257. */
  258. private function getProcess()
  259. {
  260. $taskList = $this->taskList;
  261. $currentOs = Env::get('currentOs');
  262. if ($currentOs == 1) {
  263. return (new Win($taskList));
  264. } else {
  265. return (new Linux($taskList));
  266. }
  267. }
  268. /**
  269. * 开始运行
  270. * @throws
  271. */
  272. public function start()
  273. {
  274. if (!$this->taskList) {
  275. Helper::showSysError('please add task to run');
  276. }
  277. //异常注册
  278. if (!Env::get('closeErrorRegister')) {
  279. Error::register();
  280. }
  281. //目录构建
  282. Helper::initAllPath();
  283. //进程启动
  284. $process = $this->getProcess();
  285. $process->start();
  286. }
  287. /**
  288. * 运行状态
  289. * @throws
  290. */
  291. public function status()
  292. {
  293. $process = $this->getProcess();
  294. $process->status();
  295. }
  296. /**
  297. * 停止运行
  298. * @param bool $force 是否强制
  299. * @throws
  300. */
  301. public function stop($force = false)
  302. {
  303. $process = $this->getProcess();
  304. $process->stop($force);
  305. }
  306. }