modifs.mineures sans commentaires
This commit is contained in:
		
							parent
							
								
									e9bcf77a4d
								
							
						
					
					
						commit
						4bb386167f
					
				
							
								
								
									
										3
									
								
								.idea/nur-sery.iml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								.idea/nur-sery.iml
									
									
									
										generated
									
									
									
								
							@ -1,6 +1,7 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<module type="WEB_MODULE" version="4">
 | 
					<module type="WEB_MODULE" version="4">
 | 
				
			||||||
  <component name="NewModuleRootManager">
 | 
					  <component name="NewModuleRootManager" inherit-compiler-output="true">
 | 
				
			||||||
 | 
					    <exclude-output />
 | 
				
			||||||
    <content url="file://$MODULE_DIR$">
 | 
					    <content url="file://$MODULE_DIR$">
 | 
				
			||||||
      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nur\sery\" />
 | 
					      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="nur\sery\" />
 | 
				
			||||||
      <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nur\sery\" />
 | 
					      <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="nur\sery\" />
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										67
									
								
								bin/bg-launcher.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										67
									
								
								bin/bg-launcher.php
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/php
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use nur\sery\output\msg;
 | 
				
			||||||
 | 
					use nur\sery\wip\app\app2;
 | 
				
			||||||
 | 
					use nur\sery\wip\app\cli\Application;
 | 
				
			||||||
 | 
					use nur\sery\wip\app\cli\bg_launcher;
 | 
				
			||||||
 | 
					use nur\yaml;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BgLauncherApp extends Application {
 | 
				
			||||||
 | 
					  const PROJDIR = __DIR__.'/../..';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const ACTION_INFOS = 0, ACTION_START = 1, ACTION_STOP = 2;
 | 
				
			||||||
 | 
					  const ARGS = [
 | 
				
			||||||
 | 
					    "purpose" => "lancer un script en tâche de fond",
 | 
				
			||||||
 | 
					    "usage" => "ApplicationClass args...",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ["-i", "--infos", "name" => "action", "value" => self::ACTION_INFOS,
 | 
				
			||||||
 | 
					      "help" => "Afficher des informations sur la tâche",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    ["-s", "--start", "name" => "action", "value" => self::ACTION_START,
 | 
				
			||||||
 | 
					      "help" => "Démarrer la tâche",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    ["-k", "--stop", "name" => "action", "value" => self::ACTION_STOP,
 | 
				
			||||||
 | 
					      "help" => "Arrêter la tâche",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected int $action = self::ACTION_START;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected ?array $args = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function main() {
 | 
				
			||||||
 | 
					    $appClass = $this->args[0] ?? null;
 | 
				
			||||||
 | 
					    if ($appClass === null) {
 | 
				
			||||||
 | 
					      self::die("Vous devez spécifier la classe de l'application");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $appClass = str_replace("/", "\\", $appClass);
 | 
				
			||||||
 | 
					    if (!class_exists($appClass)) {
 | 
				
			||||||
 | 
					      self::die("$appClass: classe non trouvée");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $args = array_slice($this->args, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $useRunfile = constant("$appClass::USE_RUNFILE");
 | 
				
			||||||
 | 
					    if (!$useRunfile) {
 | 
				
			||||||
 | 
					      self::die("Cette application ne supporte le lancement en tâche de fond");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $runfile = app2::with($appClass)->getRunfile();
 | 
				
			||||||
 | 
					    switch ($this->action) {
 | 
				
			||||||
 | 
					    case self::ACTION_START:
 | 
				
			||||||
 | 
					      bg_launcher::_start($args, $runfile);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case self::ACTION_STOP:
 | 
				
			||||||
 | 
					      bg_launcher::_stop($runfile);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case self::ACTION_INFOS:
 | 
				
			||||||
 | 
					      yaml::dump($runfile->read());
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$params = app2::params_getenv();
 | 
				
			||||||
 | 
					if ($params !== null) app2::init($params);
 | 
				
			||||||
 | 
					BgLauncherApp::run();
 | 
				
			||||||
@ -65,6 +65,7 @@
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	"bin": [
 | 
						"bin": [
 | 
				
			||||||
		"lib/_launch.php",
 | 
							"lib/_launch.php",
 | 
				
			||||||
 | 
							"bin/bg-launcher.php",
 | 
				
			||||||
		"nur_bin/compctl.php",
 | 
							"nur_bin/compctl.php",
 | 
				
			||||||
		"nur_bin/compdep.php",
 | 
							"nur_bin/compdep.php",
 | 
				
			||||||
		"nur_bin/cachectl.php",
 | 
							"nur_bin/cachectl.php",
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,6 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
 | 
					require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use nur\sery\wip\tools\SteamTrainApp;
 | 
					use nur\sery\tools\SteamTrainApp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SteamTrainApp::run();
 | 
					SteamTrainApp::run();
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,9 @@
 | 
				
			|||||||
namespace nur\sery\os;
 | 
					namespace nur\sery\os;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use nur\sery\cl;
 | 
					use nur\sery\cl;
 | 
				
			||||||
 | 
					use nur\sery\ExitError;
 | 
				
			||||||
use nur\sery\StateException;
 | 
					use nur\sery\StateException;
 | 
				
			||||||
 | 
					use nur\sery\wip\app\app2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class sh {
 | 
					class sh {
 | 
				
			||||||
  static final function _quote(string $value): string {
 | 
					  static final function _quote(string $value): string {
 | 
				
			||||||
@ -144,12 +146,12 @@ class sh {
 | 
				
			|||||||
    $pid = pcntl_fork();
 | 
					    $pid = pcntl_fork();
 | 
				
			||||||
    if ($pid == -1) {
 | 
					    if ($pid == -1) {
 | 
				
			||||||
      // parent, impossible de forker
 | 
					      // parent, impossible de forker
 | 
				
			||||||
      throw new StateException("unable to fork");
 | 
					      throw new ExitError(app2::EC_FORK_PARENT, "unable to fork");
 | 
				
			||||||
    } elseif ($pid) {
 | 
					    } elseif ($pid) {
 | 
				
			||||||
      // parent, fork ok
 | 
					      // parent, fork ok
 | 
				
			||||||
      pcntl_waitpid($pid, $status);
 | 
					      pcntl_waitpid($pid, $status);
 | 
				
			||||||
      if (pcntl_wifexited($status)) $retcode = pcntl_wexitstatus($status);
 | 
					      if (pcntl_wifexited($status)) $retcode = pcntl_wexitstatus($status);
 | 
				
			||||||
      else $retcode = 127;
 | 
					      else $retcode = app2::EC_FORK_CHILD;
 | 
				
			||||||
      return $retcode == 0;
 | 
					      return $retcode == 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // child, fork ok
 | 
					    // child, fork ok
 | 
				
			||||||
 | 
				
			|||||||
@ -1,27 +1,31 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace nur\sery\wip\tools;
 | 
					namespace nur\sery\tools;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use nur\sery\output\msg;
 | 
					use nur\sery\output\msg;
 | 
				
			||||||
use nur\sery\wip\app\app2;
 | 
					use nur\sery\wip\app\app2;
 | 
				
			||||||
use nur\sery\wip\app\cli\Application;
 | 
					use nur\sery\wip\app\cli\Application;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SteamTrainApp extends Application {
 | 
					class SteamTrainApp extends Application {
 | 
				
			||||||
 | 
					  const PROJDIR = __DIR__.'/../..';
 | 
				
			||||||
  const TITLE = "Train à vapeur";
 | 
					  const TITLE = "Train à vapeur";
 | 
				
			||||||
  const USE_SIGNAL_HANDLER = true;
 | 
					 | 
				
			||||||
  const USE_LOGFILE = true;
 | 
					  const USE_LOGFILE = true;
 | 
				
			||||||
  const USE_RUNFILE = true;
 | 
					  const USE_RUNFILE = true;
 | 
				
			||||||
  const USE_RUNLOCK = true;
 | 
					  const USE_RUNLOCK = true;
 | 
				
			||||||
 | 
					  const USE_SIGNAL_HANDLER = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const ARGS = [
 | 
					  const ARGS = [
 | 
				
			||||||
    "purpose" => self::TITLE,
 | 
					    "purpose" => self::TITLE,
 | 
				
			||||||
 | 
					    "description" => <<<EOT
 | 
				
			||||||
 | 
					Cette application peut être utilisée pour tester le lancement des tâches de fond
 | 
				
			||||||
 | 
					EOT,
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function main() {
 | 
					  function main() {
 | 
				
			||||||
    $runfile = app2::get()->getRunfile();
 | 
					    $count = 100;
 | 
				
			||||||
    $runfile->action("Running train...", 100);
 | 
					    app2::action("Running train...", $count);
 | 
				
			||||||
    for ($i = 1; $i <= 100; $i++) {
 | 
					    for ($i = 1; $i <= $count; $i++) {
 | 
				
			||||||
      msg::print("Tchou-tchou! x $i");
 | 
					      msg::print("Tchou-tchou! x $i");
 | 
				
			||||||
      $runfile->step();
 | 
					      app2::step();
 | 
				
			||||||
      sleep(1);
 | 
					      sleep(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
							
								
								
									
										25
									
								
								tests/wip/app/argsTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								tests/wip/app/argsTest.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace nur\sery\wip\app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use nulib\tests\TestCase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class argsTest extends TestCase {
 | 
				
			||||||
 | 
					  function testFrom_array() {
 | 
				
			||||||
 | 
					    self::assertSame([], args::from_array(null));
 | 
				
			||||||
 | 
					    self::assertSame([], args::from_array([]));
 | 
				
			||||||
 | 
					    self::assertSame([], args::from_array([false]));
 | 
				
			||||||
 | 
					    self::assertSame(["x"], args::from_array(["x", false]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self::assertSame(["--opt"], args::from_array(["--opt"]));
 | 
				
			||||||
 | 
					    self::assertSame(["--opt", "value"], args::from_array(["--opt", "value"]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self::assertSame([], args::from_array(["opt" => false]));
 | 
				
			||||||
 | 
					    self::assertSame(["--opt"], args::from_array(["opt" => true]));
 | 
				
			||||||
 | 
					    self::assertSame(["--opt", "value"], args::from_array(["opt" => "value"]));
 | 
				
			||||||
 | 
					    self::assertSame(["--opt", "42"], args::from_array(["opt" => 42]));
 | 
				
			||||||
 | 
					    self::assertSame(["--opt", "1", "2", "3", "--"], args::from_array(["opt" => [1, 2, 3]]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    self::assertSame(["x", "1", "2", "3", "y"], args::from_array(["x", [1, 2, 3], "y"]));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -269,6 +269,7 @@ class RunFile {
 | 
				
			|||||||
        "action_current_step" => 0,
 | 
					        "action_current_step" => 0,
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    app2::_dispatch_signals();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** indiquer qu'une étape est franchie dans l'action en cours */
 | 
					  /** indiquer qu'une étape est franchie dans l'action en cours */
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,6 @@ use nur\sery\cl;
 | 
				
			|||||||
use nur\sery\ExitError;
 | 
					use nur\sery\ExitError;
 | 
				
			||||||
use nur\sery\os\path;
 | 
					use nur\sery\os\path;
 | 
				
			||||||
use nur\sery\os\sh;
 | 
					use nur\sery\os\sh;
 | 
				
			||||||
use nur\sery\output\msg;
 | 
					 | 
				
			||||||
use nur\sery\php\func;
 | 
					use nur\sery\php\func;
 | 
				
			||||||
use nur\sery\str;
 | 
					use nur\sery\str;
 | 
				
			||||||
use nur\sery\ValueException;
 | 
					use nur\sery\ValueException;
 | 
				
			||||||
@ -476,6 +475,10 @@ class app2 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  #############################################################################
 | 
					  #############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const EC_UNDEAD = 247;
 | 
				
			||||||
 | 
					  const EC_REAPABLE = 248;
 | 
				
			||||||
 | 
					  const EC_FORK_CHILD = 249;
 | 
				
			||||||
 | 
					  const EC_FORK_PARENT = 250;
 | 
				
			||||||
  const EC_DISABLED = 251;
 | 
					  const EC_DISABLED = 251;
 | 
				
			||||||
  const EC_LOCKED = 252;
 | 
					  const EC_LOCKED = 252;
 | 
				
			||||||
  const EC_BAD_COMMAND = 253;
 | 
					  const EC_BAD_COMMAND = 253;
 | 
				
			||||||
@ -536,4 +539,14 @@ class app2 {
 | 
				
			|||||||
      throw new ExitError(self::EC_DISABLED, "Planifications désactivées. La tâche n'a pas été lancée");
 | 
					      throw new ExitError(self::EC_DISABLED, "Planifications désactivées. La tâche n'a pas été lancée");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #############################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static function action(?string $title, ?int $maxSteps=null): void {
 | 
				
			||||||
 | 
					    self::get()->getRunfile()->action($title, $maxSteps);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static function step(int $nbSteps=1): void {
 | 
				
			||||||
 | 
					    self::get()->getRunfile()->step($nbSteps);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										39
									
								
								wip/app/args.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								wip/app/args.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					<?php
 | 
				
			||||||
 | 
					namespace nur\sery\wip\app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use nur\sery\A;
 | 
				
			||||||
 | 
					use nur\sery\str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class args {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * transformer une liste d'argument de la forme
 | 
				
			||||||
 | 
					   * - ["myArg" => $value]  devient  ["--my-arg", "$value"]
 | 
				
			||||||
 | 
					   * - ["myOpt" => true]    devient  ["--my-opt"]
 | 
				
			||||||
 | 
					   * - ["myOpt" => false]   est omis
 | 
				
			||||||
 | 
					   * - les autres valeurs sont prises telles quelles
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  static function from_array(?array $array): array {
 | 
				
			||||||
 | 
					    $args = [];
 | 
				
			||||||
 | 
					    if ($array === null) return $args;
 | 
				
			||||||
 | 
					    $index = 0;
 | 
				
			||||||
 | 
					    foreach ($array as $arg => $value) {
 | 
				
			||||||
 | 
					      if ($value === false) continue;
 | 
				
			||||||
 | 
					      if ($arg === $index) {
 | 
				
			||||||
 | 
					        $index++;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        $arg = str::us2camel($arg);
 | 
				
			||||||
 | 
					        $arg = str::camel2us($arg, false, "-");
 | 
				
			||||||
 | 
					        $arg = str_replace("_", "-", $arg);
 | 
				
			||||||
 | 
					        $args[] = "--$arg";
 | 
				
			||||||
 | 
					        if (is_array($value)) $value[] = "--";
 | 
				
			||||||
 | 
					        elseif ($value === true) $value = null;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (is_array($value)) {
 | 
				
			||||||
 | 
					        A::merge($args, array_map("strval", $value));
 | 
				
			||||||
 | 
					      } elseif ($value !== null) {
 | 
				
			||||||
 | 
					        $args[] = "$value";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return $args;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,5 +1,119 @@
 | 
				
			|||||||
<?php
 | 
					<?php
 | 
				
			||||||
namespace nur\sery\wip\app\cli;
 | 
					namespace nur\sery\wip\app\cli;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use nur\sery\ExitError;
 | 
				
			||||||
 | 
					use nur\sery\file\TmpfileWriter;
 | 
				
			||||||
 | 
					use nur\sery\os\path;
 | 
				
			||||||
 | 
					use nur\sery\os\proc\Cmd;
 | 
				
			||||||
 | 
					use nur\sery\output\msg;
 | 
				
			||||||
 | 
					use nur\sery\StateException;
 | 
				
			||||||
 | 
					use nur\sery\wip\app\app2;
 | 
				
			||||||
 | 
					use nur\sery\wip\app\args;
 | 
				
			||||||
 | 
					use nur\sery\wip\app\RunFile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class bg_launcher {
 | 
					class bg_launcher {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * transformer une liste d'argument de la forme
 | 
				
			||||||
 | 
					   * - ["myArg" => $value]  devient  ["--my-arg", "$value"]
 | 
				
			||||||
 | 
					   * - ["myOpt" => true]    devient  ["--my-opt"]
 | 
				
			||||||
 | 
					   * - ["myOpt" => false]   est momis
 | 
				
			||||||
 | 
					   * - les valeurs séquentielles sont prises telles quelles
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  static function verifix_args(array $args): array {
 | 
				
			||||||
 | 
					    $args = args::from_array($args);
 | 
				
			||||||
 | 
					    # corriger le chemin de l'application pour qu'il soit absolu et normalisé
 | 
				
			||||||
 | 
					    $args[0] = path::abspath($args[0]);
 | 
				
			||||||
 | 
					    return $args;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static function launch(string $appClass, array $args): int {
 | 
				
			||||||
 | 
					    $app = app2::get();
 | 
				
			||||||
 | 
					    $vendorBindir = $app->getVendorbindir();
 | 
				
			||||||
 | 
					    $launch_php = "$vendorBindir/_launch.php";
 | 
				
			||||||
 | 
					    if (!file_exists($launch_php)) {
 | 
				
			||||||
 | 
					      $launch_php = __DIR__."/../../lib/_launch.php";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $tmpfile = new TmpfileWriter();
 | 
				
			||||||
 | 
					    $tmpfile->keep()->serialize($app->getParams());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $args = self::verifix_args($args);
 | 
				
			||||||
 | 
					    $cmd = new Cmd([
 | 
				
			||||||
 | 
					      $launch_php,
 | 
				
			||||||
 | 
					      "--internal-use", $tmpfile->getFile(),
 | 
				
			||||||
 | 
					      $appClass, "--", ...$args,
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    $cmd->addRedir("both", "/tmp/nulib_app_launcher-launch.log");
 | 
				
			||||||
 | 
					    $cmd->passthru($exitcode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # attendre un peu que la commande aie le temps de s'initialiser
 | 
				
			||||||
 | 
					    sleep(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    $tmpfile->close();
 | 
				
			||||||
 | 
					    return $exitcode;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static function _start(array $args, Runfile $runfile): bool {
 | 
				
			||||||
 | 
					    if ($runfile->warnIfLocked()) return false;
 | 
				
			||||||
 | 
					    $pid = pcntl_fork();
 | 
				
			||||||
 | 
					    if ($pid == -1) {
 | 
				
			||||||
 | 
					      # parent, impossible de forker
 | 
				
			||||||
 | 
					      throw new ExitError(app2::EC_FORK_PARENT, "Unable to fork");
 | 
				
			||||||
 | 
					    } elseif ($pid) {
 | 
				
			||||||
 | 
					      # parent, fork ok
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      ## child, fork ok
 | 
				
			||||||
 | 
					      # Créer un groupe de process, pour pouvoir tuer tous les enfants en même temps
 | 
				
			||||||
 | 
					      $runfile->tm_startPg();
 | 
				
			||||||
 | 
					      $logfile = $runfile->getLogfile() ?? "/tmp/NULIB_APP_app_start.log";
 | 
				
			||||||
 | 
					      $pid = posix_getpid();
 | 
				
			||||||
 | 
					      $exitcode = app2::EC_FORK_CHILD;
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        # puis lancer la commande
 | 
				
			||||||
 | 
					        $cmd = new Cmd($args);
 | 
				
			||||||
 | 
					        $cmd->addSource("/g/init.env");
 | 
				
			||||||
 | 
					        $cmd->addRedir("both", $logfile, true);
 | 
				
			||||||
 | 
					        msg::debug("$pid: launching\n".$cmd->getCmd());
 | 
				
			||||||
 | 
					        $cmd->fork_exec($exitcode);
 | 
				
			||||||
 | 
					        msg::debug("$pid: exitcode=$exitcode");
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      } finally {
 | 
				
			||||||
 | 
					        $runfile->wfStopped($exitcode);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static function _stop(Runfile $runfile): void {
 | 
				
			||||||
 | 
					    $data = $runfile->read();
 | 
				
			||||||
 | 
					    $pid = $data["pg_pid"];
 | 
				
			||||||
 | 
					    if ($pid === null) {
 | 
				
			||||||
 | 
					      msg::warning("$data[name]: groupe de process inconnu");
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    msg::action("kill $pid");
 | 
				
			||||||
 | 
					    if (!posix_kill(-$pid, SIGKILL)) {
 | 
				
			||||||
 | 
					      switch (posix_get_last_error()) {
 | 
				
			||||||
 | 
					      case PCNTL_ESRCH:
 | 
				
			||||||
 | 
					        msg::afailure("process inexistant");
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case PCNTL_EPERM:
 | 
				
			||||||
 | 
					        msg::afailure("process non accessible");
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case PCNTL_EINVAL:
 | 
				
			||||||
 | 
					        msg::afailure("signal invalide");
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $timeout = 10;
 | 
				
			||||||
 | 
					    while ($runfile->tm_isUndead($pid)) {
 | 
				
			||||||
 | 
					      sleep(1);
 | 
				
			||||||
 | 
					      if (--$timeout == 0) {
 | 
				
			||||||
 | 
					        msg::afailure("impossible d'arrêter la tâche");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $runfile->wfStopped(app2::EC_REAPABLE);
 | 
				
			||||||
 | 
					    msg::asuccess();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,137 +0,0 @@
 | 
				
			|||||||
<?php
 | 
					 | 
				
			||||||
namespace nur\sery\wip\app;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use nur\sery\app\Runfile;
 | 
					 | 
				
			||||||
use nur\sery\cl;
 | 
					 | 
				
			||||||
use nur\sery\file\TmpfileWriter;
 | 
					 | 
				
			||||||
use nur\sery\os\path;
 | 
					 | 
				
			||||||
use nur\sery\os\proc\Cmd;
 | 
					 | 
				
			||||||
use nur\sery\output\msg;
 | 
					 | 
				
			||||||
use nur\sery\StateException;
 | 
					 | 
				
			||||||
use nur\sery\str;
 | 
					 | 
				
			||||||
use nur\sery\wip\app\app2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class launcher {
 | 
					 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
   * transformer une liste d'argument de la forme
 | 
					 | 
				
			||||||
   * - ["myArg" => $value]  devient  ["--my-arg", "$value"]
 | 
					 | 
				
			||||||
   * - ["myOpt" => true]    devient  ["--my-opt"]
 | 
					 | 
				
			||||||
   * - ["myOpt" => false]   est momis
 | 
					 | 
				
			||||||
   * - les valeurs séquentielles sont prises telles quelles
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  static function verifix_args(array $args): array {
 | 
					 | 
				
			||||||
    if (!cl::is_list($args)) {
 | 
					 | 
				
			||||||
      $fixedArgs = [];
 | 
					 | 
				
			||||||
      $index = 0;
 | 
					 | 
				
			||||||
      foreach ($args as $arg => $value) {
 | 
					 | 
				
			||||||
        if ($arg === $index) {
 | 
					 | 
				
			||||||
          $index++;
 | 
					 | 
				
			||||||
          $fixedArgs[] = $value;
 | 
					 | 
				
			||||||
          continue;
 | 
					 | 
				
			||||||
        } elseif ($value === false) {
 | 
					 | 
				
			||||||
          continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        $arg = str::us2camel($arg);
 | 
					 | 
				
			||||||
        $arg = str::camel2us($arg, false, "-");
 | 
					 | 
				
			||||||
        $arg = str_replace("_", "-", $arg);
 | 
					 | 
				
			||||||
        $fixedArgs[] = "--$arg";
 | 
					 | 
				
			||||||
        if ($value !== true) $fixedArgs[] = "$value";
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      $args = $fixedArgs;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    # corriger le chemin de l'application pour qu'il soit absolu et normalisé
 | 
					 | 
				
			||||||
    $args[0] = path::abspath($args[0]);
 | 
					 | 
				
			||||||
    return $args;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  static function launch(string $appClass, array $args): int {
 | 
					 | 
				
			||||||
    $app = app2::get();
 | 
					 | 
				
			||||||
    $vendorBindir = $app->getVendorbindir();
 | 
					 | 
				
			||||||
    $launch_php = "$vendorBindir/_launch.php";
 | 
					 | 
				
			||||||
    if (!file_exists($launch_php)) {
 | 
					 | 
				
			||||||
      $launch_php = __DIR__."/../../lib/_launch.php";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    $tmpfile = new TmpfileWriter();
 | 
					 | 
				
			||||||
    $tmpfile->keep()->serialize($app->getParams());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $args = self::verifix_args($args);
 | 
					 | 
				
			||||||
    $cmd = new Cmd([
 | 
					 | 
				
			||||||
      $launch_php,
 | 
					 | 
				
			||||||
      "--internal-use", $tmpfile->getFile(),
 | 
					 | 
				
			||||||
      $appClass, "--", ...$args,
 | 
					 | 
				
			||||||
    ]);
 | 
					 | 
				
			||||||
    $cmd->addRedir("both", "/tmp/nulib_app_launcher-launch.log");
 | 
					 | 
				
			||||||
    $cmd->passthru($exitcode);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # attendre un peu que la commande aie le temps de s'initialiser
 | 
					 | 
				
			||||||
    sleep(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $tmpfile->close();
 | 
					 | 
				
			||||||
    return $exitcode;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  static function _start(array $args, Runfile $runfile): bool {
 | 
					 | 
				
			||||||
    if ($runfile->warnIfLocked()) return false;
 | 
					 | 
				
			||||||
    $pid = pcntl_fork();
 | 
					 | 
				
			||||||
    if ($pid == -1) {
 | 
					 | 
				
			||||||
      # parent, impossible de forker
 | 
					 | 
				
			||||||
      throw new StateException("unable to fork");
 | 
					 | 
				
			||||||
    } elseif ($pid) {
 | 
					 | 
				
			||||||
      # parent, fork ok
 | 
					 | 
				
			||||||
      return true;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
      ## child, fork ok
 | 
					 | 
				
			||||||
      # Créer un groupe de process, pour pouvoir tuer tous les enfants en même temps
 | 
					 | 
				
			||||||
      $runfile->tm_startPg();
 | 
					 | 
				
			||||||
      $logfile = $runfile->getLogfile() ?? "/tmp/nulib_app_launcher-_start.log";
 | 
					 | 
				
			||||||
      $pid = posix_getpid();
 | 
					 | 
				
			||||||
      $exitcode = -776;
 | 
					 | 
				
			||||||
      try {
 | 
					 | 
				
			||||||
        # puis lancer la commande
 | 
					 | 
				
			||||||
        $cmd = new Cmd($args);
 | 
					 | 
				
			||||||
        $cmd->addSource("/g/init.env");
 | 
					 | 
				
			||||||
        $cmd->addRedir("both", $logfile, true);
 | 
					 | 
				
			||||||
        msg::debug("$pid: launching\n".$cmd->getCmd());
 | 
					 | 
				
			||||||
        $cmd->fork_exec($exitcode);
 | 
					 | 
				
			||||||
        msg::debug("$pid: exitcode=$exitcode");
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
      } finally {
 | 
					 | 
				
			||||||
        $runfile->wfStopped($exitcode);
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  static function _stop(Runfile $runfile): void {
 | 
					 | 
				
			||||||
    $data = $runfile->read();
 | 
					 | 
				
			||||||
    $pid = $data["pg_pid"];
 | 
					 | 
				
			||||||
    if ($pid === null) {
 | 
					 | 
				
			||||||
      msg::warning("$data[name]: groupe de process inconnu");
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    msg::action("kill $pid");
 | 
					 | 
				
			||||||
    if (!posix_kill(-$pid, SIGKILL)) {
 | 
					 | 
				
			||||||
      switch (posix_get_last_error()) {
 | 
					 | 
				
			||||||
      case PCNTL_ESRCH:
 | 
					 | 
				
			||||||
        msg::afailure("process inexistant");
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case PCNTL_EPERM:
 | 
					 | 
				
			||||||
        msg::afailure("process non accessible");
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      case PCNTL_EINVAL:
 | 
					 | 
				
			||||||
        msg::afailure("signal invalide");
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    $timeout = 10;
 | 
					 | 
				
			||||||
    while ($runfile->tm_isUndead($pid)) {
 | 
					 | 
				
			||||||
      sleep(1);
 | 
					 | 
				
			||||||
      if (--$timeout == 0) {
 | 
					 | 
				
			||||||
        msg::afailure("impossible d'arrêter la tâche");
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    $runfile->wfStopped(-778);
 | 
					 | 
				
			||||||
    msg::asuccess();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user