125 lines
3.5 KiB
PHP
125 lines
3.5 KiB
PHP
<?php
|
|
namespace nur\sery\tools;
|
|
|
|
use nulib\app\RunFile;
|
|
use nulib\ExitError;
|
|
use nulib\ext\yaml;
|
|
use nulib\os\path;
|
|
use nulib\os\proc\Cmd;
|
|
use nulib\os\sh;
|
|
use nulib\output\msg;
|
|
use nur\sery\app;
|
|
use nur\sery\app\cli\Application;
|
|
|
|
class BgLauncherApp extends Application {
|
|
const ACTION_INFOS = 0, ACTION_START = 1, ACTION_STOP = 2;
|
|
const ARGS = [
|
|
"purpose" => "lancer un script en tâche de fond",
|
|
"usage" => "ApplicationClass args...",
|
|
|
|
"sections" => [
|
|
parent::VERBOSITY_SECTION,
|
|
],
|
|
|
|
["-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;
|
|
|
|
static function show_infos(RunFile $runfile, ?int $level=null): void {
|
|
msg::print($runfile->getDesc(), $level);
|
|
msg::print(yaml::with(["data" => $runfile->read()]), ($level ?? 0) - 1);
|
|
}
|
|
|
|
function main() {
|
|
$args = $this->args;
|
|
|
|
$appClass = $args[0] ?? null;
|
|
if ($appClass === null) {
|
|
self::die("Vous devez spécifier la classe de l'application");
|
|
}
|
|
$appClass = $args[0] = str_replace("/", "\\", $appClass);
|
|
if (!class_exists($appClass)) {
|
|
self::die("$appClass: classe non trouvée");
|
|
}
|
|
|
|
$useRunfile = constant("$appClass::USE_RUNFILE");
|
|
if (!$useRunfile) {
|
|
self::die("Cette application ne supporte le lancement en tâche de fond");
|
|
}
|
|
|
|
$runfile = app::with($appClass)->getRunfile();
|
|
switch ($this->action) {
|
|
case self::ACTION_START:
|
|
$argc = count($args);
|
|
$appClass::_manage_runfile($argc, $args, $runfile);
|
|
if ($runfile->warnIfLocked()) self::exit(app::EC_LOCKED);
|
|
array_splice($args, 0, 0, [
|
|
PHP_BINARY,
|
|
path::abspath(NULIB_APP_app_launcher),
|
|
]);
|
|
app::params_putenv();
|
|
self::_start($args, $runfile);
|
|
break;
|
|
case self::ACTION_STOP:
|
|
self::_stop($runfile);
|
|
self::show_infos($runfile, -1);
|
|
break;
|
|
case self::ACTION_INFOS:
|
|
self::show_infos($runfile);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public static function _start(array $args, Runfile $runfile): void {
|
|
$pid = pcntl_fork();
|
|
if ($pid == -1) {
|
|
# parent, impossible de forker
|
|
throw new ExitError(app::EC_FORK_PARENT, "Unable to fork");
|
|
} elseif (!$pid) {
|
|
# child, fork ok
|
|
$runfile->wfPrepare($pid);
|
|
$outfile = $runfile->getOutfile() ?? "/tmp/NULIB_APP_app_console.out";
|
|
$exitcode = app::EC_FORK_CHILD;
|
|
try {
|
|
# rediriger STDIN, STDOUT et STDERR
|
|
fclose(fopen($outfile, "wb")); // vider le fichier
|
|
fclose(STDIN); $in = fopen("/dev/null", "rb");
|
|
fclose(STDOUT); $out = fopen($outfile, "ab");
|
|
fclose(STDERR); $err = fopen($outfile, "ab");
|
|
# puis lancer la commande
|
|
$cmd = new Cmd($args);
|
|
$cmd->addSource("/g/init.env");
|
|
$cmd->addRedir("both", $outfile, true);
|
|
$cmd->fork_exec($exitcode, false);
|
|
sh::_waitpid(-$pid, $exitcode);
|
|
} finally {
|
|
$runfile->wfReaped($exitcode);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static function _stop(Runfile $runfile): bool {
|
|
$data = $runfile->read();
|
|
$pid = $runfile->_getCid($data);
|
|
msg::action("stop $pid");
|
|
if ($runfile->wfKill($reason)) {
|
|
msg::asuccess();
|
|
return true;
|
|
} else {
|
|
msg::afailure($reason);
|
|
return false;
|
|
}
|
|
}
|
|
}
|