windows.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. /**
  3. * Start file for windows
  4. */
  5. chdir(__DIR__);
  6. // Eloquent需要原生mbstring;Windows工作进程启动时继承项目扩展配置。
  7. if (!extension_loaded('mbstring')) {
  8. $extraIni = __DIR__ . '/config/php';
  9. $scanPath = getenv('PHP_INI_SCAN_DIR') ?: '';
  10. if (!in_array($extraIni, explode(PATH_SEPARATOR, $scanPath), true)) {
  11. putenv('PHP_INI_SCAN_DIR=' . ($scanPath !== '' ? $scanPath . PATH_SEPARATOR : '') . $extraIni);
  12. }
  13. }
  14. require_once __DIR__ . '/vendor/autoload.php';
  15. use Dotenv\Dotenv;
  16. use support\App;
  17. use Workerman\Worker;
  18. ini_set('display_errors', 'on');
  19. error_reporting(E_ALL);
  20. if (class_exists('Dotenv\Dotenv') && file_exists(base_path() . '/.env')) {
  21. if (method_exists('Dotenv\Dotenv', 'createUnsafeImmutable')) {
  22. Dotenv::createUnsafeImmutable(base_path())->load();
  23. } else {
  24. Dotenv::createMutable(base_path())->load();
  25. }
  26. }
  27. App::loadAllConfig(['route']);
  28. $errorReporting = config('app.error_reporting');
  29. if (isset($errorReporting)) {
  30. error_reporting($errorReporting);
  31. }
  32. $runtimeProcessPath = runtime_path() . DIRECTORY_SEPARATOR . '/windows';
  33. $paths = [
  34. $runtimeProcessPath,
  35. runtime_path('logs'),
  36. runtime_path('views')
  37. ];
  38. foreach ($paths as $path) {
  39. if (!is_dir($path)) {
  40. mkdir($path, 0777, true);
  41. }
  42. }
  43. $processFiles = [];
  44. if (config('server.listen')) {
  45. $processFiles[] = __DIR__ . DIRECTORY_SEPARATOR . 'start.php';
  46. }
  47. foreach (config('process', []) as $processName => $config) {
  48. $processFiles[] = write_process_file($runtimeProcessPath, $processName, '');
  49. }
  50. foreach (config('plugin', []) as $firm => $projects) {
  51. foreach ($projects as $name => $project) {
  52. if (!is_array($project)) {
  53. continue;
  54. }
  55. foreach ($project['process'] ?? [] as $processName => $config) {
  56. $processFiles[] = write_process_file($runtimeProcessPath, $processName, "$firm.$name");
  57. }
  58. }
  59. foreach ($projects['process'] ?? [] as $processName => $config) {
  60. $processFiles[] = write_process_file($runtimeProcessPath, $processName, $firm);
  61. }
  62. }
  63. function write_process_file($runtimeProcessPath, $processName, $firm): string
  64. {
  65. $processParam = $firm ? "plugin.$firm.$processName" : $processName;
  66. $configParam = $firm ? "config('plugin.$firm.process')['$processName']" : "config('process')['$processName']";
  67. $fileContent = <<<EOF
  68. <?php
  69. require_once __DIR__ . '/../../vendor/autoload.php';
  70. use Workerman\Worker;
  71. use Workerman\Connection\TcpConnection;
  72. use Webman\Config;
  73. use support\App;
  74. ini_set('display_errors', 'on');
  75. error_reporting(E_ALL);
  76. if (is_callable('opcache_reset')) {
  77. opcache_reset();
  78. }
  79. if (!\$appConfigFile = config_path('app.php')) {
  80. throw new RuntimeException('Config file not found: app.php');
  81. }
  82. \$appConfig = require \$appConfigFile;
  83. if (\$timezone = \$appConfig['default_timezone'] ?? '') {
  84. date_default_timezone_set(\$timezone);
  85. }
  86. App::loadAllConfig(['route']);
  87. worker_start('$processParam', $configParam);
  88. if (DIRECTORY_SEPARATOR != "/") {
  89. Worker::\$logFile = config('server')['log_file'] ?? Worker::\$logFile;
  90. TcpConnection::\$defaultMaxPackageSize = config('server')['max_package_size'] ?? 10*1024*1024;
  91. }
  92. Worker::runAll();
  93. EOF;
  94. $processFile = $runtimeProcessPath . DIRECTORY_SEPARATOR . "start_$processParam.php";
  95. file_put_contents($processFile, $fileContent);
  96. return $processFile;
  97. }
  98. if ($monitorConfig = config('process.monitor.constructor')) {
  99. $monitorHandler = config('process.monitor.handler');
  100. $monitor = new $monitorHandler(...array_values($monitorConfig));
  101. }
  102. function popen_processes($processFiles)
  103. {
  104. $cmd = '"' . PHP_BINARY . '" ' . implode(' ', $processFiles);
  105. $descriptorspec = [STDIN, STDOUT, STDOUT];
  106. $resource = proc_open($cmd, $descriptorspec, $pipes, null, null, ['bypass_shell' => true]);
  107. if (!$resource) {
  108. exit("Can not execute $cmd\r\n");
  109. }
  110. return $resource;
  111. }
  112. $resource = popen_processes($processFiles);
  113. echo "\r\n";
  114. while (1) {
  115. sleep(1);
  116. if (!empty($monitor) && $monitor->checkAllFilesChange()) {
  117. $status = proc_get_status($resource);
  118. $pid = $status['pid'];
  119. shell_exec("taskkill /F /T /PID $pid");
  120. proc_close($resource);
  121. $resource = popen_processes($processFiles);
  122. }
  123. }