Schedule.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. namespace app\command\schedule;
  3. use app\command\WorkerCommand;
  4. use app\dict\schedule\ScheduleDict;
  5. use app\service\core\schedule\CoreScheduleService;
  6. use think\console\Command;
  7. use think\console\Input;
  8. use think\console\input\Argument;
  9. use think\console\input\Option;
  10. use think\console\Output;
  11. use Workerman\Crontab\Crontab;
  12. use Workerman\Worker;
  13. class Schedule extends Command
  14. {
  15. use WorkerCommand;
  16. public function configure()
  17. {
  18. // 指令配置
  19. $this->setName('cron:schedule')
  20. ->addArgument('action', Argument::OPTIONAL, "start|stop|restart|reload|status|connections", 'start')
  21. ->addOption('mode', 'm', Option::VALUE_OPTIONAL, 'Run the workerman server in daemon mode.')
  22. ->setDescription('定时任务,类似linux的crontab。支持秒级别定时。');
  23. }
  24. /**
  25. * 执行任务
  26. * @return void
  27. */
  28. protected function execute(Input $input, Output $output)
  29. {
  30. $this->resetCli($input, $output);
  31. Worker::$pidFile = runtime_path() . 'workerman_schedule.pid';
  32. $worker = new Worker();
  33. $worker->name = 'schedule_work';
  34. $worker->count = 1;
  35. $output->writeln('[' . date('Y-m-d H:i:s') . ']' . " Schedule Starting...");
  36. // 设置时区,避免运行结果与预期不一致
  37. date_default_timezone_set('PRC');
  38. $worker->onWorkerStart = function() use ($output) {
  39. // // 每分钟的第1秒执行.用于计划任务是否仍在执行
  40. new Crontab('*/10 * * * * *', function() {
  41. $file = root_path('runtime') . '.schedule';
  42. file_put_contents($file, time());
  43. });
  44. $core_schedule_service = new CoreScheduleService();
  45. //查询所有的计划任务
  46. $task_list = $core_schedule_service->getList([ 'status' => ScheduleDict::ON ]);
  47. $output->writeln('[' . date('Y-m-d H:i:s') . ']' . " Schedule Started.");
  48. foreach ($task_list as $item) {
  49. //获取定时任务时间字符串
  50. new Crontab($this->getCrontab($item[ 'time' ]), function() use ($core_schedule_service, $item, $output) {
  51. if (!empty($item[ 'class' ])) {
  52. $core_schedule_service->execute($item, $output);
  53. }
  54. });
  55. }
  56. };
  57. Worker::runAll();
  58. }
  59. /**
  60. * 获取计划任务所需的时间字符串
  61. * 0 1 2 3 4 5
  62. * | | | | | |
  63. * | | | | | +------ day of week (0 - 6) (Sunday=0)
  64. * | | | | +------ month (1 - 12)
  65. * | | | +-------- day of month (1 - 31)
  66. * | | +---------- hour (0 - 23)
  67. * | +------------ min (0 - 59)
  68. * +-------------- sec (0-59)[可省略,如果没有0位,则最小时间粒度是分钟]
  69. * @param $data
  70. * @return string
  71. */
  72. protected function getCrontab($data) : string
  73. {
  74. $sec = $data[ 'sec' ] ?? '*';
  75. $min = $data[ 'min' ] ?? '*';
  76. $hour = $data[ 'hour' ] ?? '*';
  77. $day = $data[ 'day' ] ?? '*';
  78. $week = $data[ 'week' ] ?? '*';
  79. $type = $data[ 'type' ] ?? '';
  80. switch ($type) {
  81. case 'sec':// 每隔几秒
  82. $crontab = '*/' . $sec . ' * * * * *';
  83. break;
  84. case 'min':// 每隔几分
  85. $crontab = '0 */' . $min . ' * * * *';
  86. break;
  87. case 'hour':// 每隔几时第几分钟执行
  88. $crontab = '0 ' . $min . ' */' . $hour . ' * * *';
  89. break;
  90. case 'day':// 每隔几日第几小时第几分钟执行
  91. $crontab = '0 ' . $min . ' ' . $hour . ' */' . $day . ' * *';
  92. break;
  93. case 'week':// 每周一次,周几具体时间执行
  94. $crontab = '0 ' . $min . ' ' . $hour . ' * * ' . $week;
  95. break;
  96. case 'month':// 每月一次,某日具体时间执行
  97. $crontab = '0 ' . $min . ' ' . $hour . ' ' . $day . ' * *';
  98. break;
  99. }
  100. return $crontab ?? '0 */1 * * * *';
  101. }
  102. }