modifs.mineures sans commentaires
This commit is contained in:
parent
21688ac0e1
commit
f82c847ec2
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
namespace nur\sery\app;
|
||||
|
||||
use nur\b\proc\Cmd;
|
||||
use nur\sery\os\proc\Cmd;
|
||||
use nur\sery\output\msg;
|
||||
use nur\sery\StateException;
|
||||
|
||||
|
@ -33,6 +33,7 @@ class launcher {
|
|||
# puis lancer la commande
|
||||
$cmd = new Cmd($args);
|
||||
#XXX fichier de log?
|
||||
#XXX charger /g/init.env
|
||||
$cmd->addRedir("null");
|
||||
$cmd->fork_exec($exitcode);
|
||||
} finally {
|
||||
|
|
|
@ -0,0 +1,196 @@
|
|||
<?php
|
||||
namespace nur\sery\os\proc;
|
||||
|
||||
use nur\A;
|
||||
use nur\base;
|
||||
use nur\sery\os\sh;
|
||||
use nur\shell;
|
||||
|
||||
abstract class AbstractCmd implements ICmd {
|
||||
private bool $needsStdin;
|
||||
|
||||
private bool $needsTty;
|
||||
|
||||
protected ?array $vars;
|
||||
|
||||
protected array $cmds;
|
||||
|
||||
function __construct() {
|
||||
$this->needsStdin = true;
|
||||
$this->needsTty = true;
|
||||
$this->vars = null;
|
||||
$this->cmds = [];
|
||||
}
|
||||
|
||||
function then($cmd, ?string $input=null, ?string $output=null): Cmd {
|
||||
if ($this instanceof Cmd) {
|
||||
$this->add($cmd, $input, $output);
|
||||
return $this;
|
||||
} else {
|
||||
return (new Cmd($this))->add($cmd, $input, $output);
|
||||
}
|
||||
}
|
||||
|
||||
function or($cmd, ?string $input=null, ?string $output=null): CmdOr {
|
||||
if ($this instanceof CmdOr) {
|
||||
$this->add($cmd, $input, $output);
|
||||
return $this;
|
||||
} else {
|
||||
return (new CmdOr($this))->add($cmd, $input, $output);
|
||||
}
|
||||
}
|
||||
|
||||
function and($cmd, ?string $input=null, ?string $output=null): CmdAnd {
|
||||
if ($this instanceof CmdAnd) {
|
||||
$this->add($cmd, $input, $output);
|
||||
return $this;
|
||||
} else {
|
||||
return (new CmdAnd($this))->add($cmd, $input, $output);
|
||||
}
|
||||
}
|
||||
|
||||
function pipe($cmd): CmdPipe {
|
||||
if ($this instanceof CmdPipe) {
|
||||
$this->add($cmd);
|
||||
return $this;
|
||||
} else {
|
||||
return new CmdPipe([$this, $cmd]);
|
||||
}
|
||||
}
|
||||
|
||||
function isNeedsStdin(): bool {
|
||||
return $this->needsStdin;
|
||||
}
|
||||
|
||||
function setNeedsStdin(bool $needsStdin): void {
|
||||
$this->needsStdin = $needsStdin;
|
||||
}
|
||||
|
||||
function isNeedsTty(): bool {
|
||||
return $this->needsTty;
|
||||
}
|
||||
|
||||
function setNeedsTty(bool $needsTty): void {
|
||||
$this->needsTty = $needsTty;
|
||||
}
|
||||
|
||||
function addLiteralVars($vars, ?string $sep=null): void {
|
||||
if (base::z($vars)) return;
|
||||
if (is_array($vars)) {
|
||||
if ($sep === null) $sep = "\n";
|
||||
$vars = implode($sep, $vars);
|
||||
}
|
||||
A::append($this->vars, strval($vars));
|
||||
}
|
||||
|
||||
function addVars(?array $vars): void {
|
||||
if ($vars === null) return;
|
||||
foreach ($vars as $name => $value) {
|
||||
$var = [];
|
||||
if (!is_array($value)) $var[] = "export ";
|
||||
A::merge($var, [$name, "=", shell::quote($value)]);
|
||||
A::append($this->vars, implode("", $var));
|
||||
}
|
||||
}
|
||||
|
||||
function getVars(?string $sep=null): ?string {
|
||||
if ($this->vars === null) return null;
|
||||
if ($sep === null) $sep = "\n";
|
||||
return implode($sep, $this->vars);
|
||||
}
|
||||
|
||||
function addPrefix($prefix): void {
|
||||
$count = count($this->cmds);
|
||||
if ($count == 0) return;
|
||||
$cmd =& $this->cmds[$count - 1];
|
||||
if ($cmd instanceof ICmd) {
|
||||
$cmd->addPrefix($prefix);
|
||||
} elseif (is_array($prefix)) {
|
||||
$prefix = shell::join($prefix);
|
||||
$cmd = "$prefix $cmd";
|
||||
} else {
|
||||
$cmd = "$prefix $cmd";
|
||||
}
|
||||
}
|
||||
|
||||
function addRedir(?string $redir, $output=null, bool $append=false, $input=null): void {
|
||||
$count = count($this->cmds);
|
||||
if ($count == 0) return;
|
||||
|
||||
if ($output !== null) $output = escapeshellarg($output);
|
||||
if ($input !== null) $input = escapeshellarg($input);
|
||||
if ($redir === "default") $redir = null;
|
||||
$gt = $append? ">>": ">";
|
||||
if ($redir === null) {
|
||||
$redirs = [];
|
||||
if ($input !== null) $redirs[] = "<$input";
|
||||
if ($output !== null) $redirs[] = "$gt$output";
|
||||
if ($redirs) $redir = implode(" ", $redir);
|
||||
} else {
|
||||
switch ($redir) {
|
||||
case "outonly":
|
||||
case "noerr":
|
||||
if ($output !== null) $redir = "$gt$output 2>/dev/null";
|
||||
else $redir = "2>/dev/null";
|
||||
break;
|
||||
case "erronly":
|
||||
case "noout":
|
||||
if ($output !== null) $redir = "2$gt$output >/dev/null";
|
||||
else $redir = "2>&1 >/dev/null";
|
||||
break;
|
||||
case "both":
|
||||
case "err2out":
|
||||
if ($output !== null) $redir = "$gt$output 2>&1";
|
||||
else $redir = "2>&1";
|
||||
break;
|
||||
case "none":
|
||||
case "null":
|
||||
$redir = ">/dev/null 2>&1";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($redir !== null) {
|
||||
$cmd =& $this->cmds[$count - 1];
|
||||
if ($cmd instanceof ICmd) {
|
||||
$cmd->addRedir($redir);
|
||||
} else {
|
||||
$cmd = "$cmd $redir";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract function getCmd(?string $sep=null): string;
|
||||
|
||||
function passthru(int &$retcode=null): bool {
|
||||
passthru($this->getCmd(), $retcode);
|
||||
return $retcode == 0;
|
||||
}
|
||||
|
||||
function system(string &$output=null, int &$retcode=null): bool {
|
||||
$last_line = system($this->getCmd(), $retcode);
|
||||
if ($last_line !== false) $output = $last_line;
|
||||
return $retcode == 0;
|
||||
}
|
||||
|
||||
function exec(array &$output=null, int &$retcode=null): bool {
|
||||
exec($this->getCmd(), $output, $retcode);
|
||||
return $retcode == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* retourner true s'il faut utiliser `exec` avec {@link fork_exec()}
|
||||
*
|
||||
* ne pas utiliser `exec` si des variables sont définies ou si c'est une
|
||||
* composition de plusieurs commandes
|
||||
*/
|
||||
protected function useExec(): bool {
|
||||
return $this->vars === null && count($this->cmds) == 1;
|
||||
}
|
||||
|
||||
function fork_exec(int &$retcode=null): bool {
|
||||
$cmd = $this->getCmd();
|
||||
if ($this->useExec()) $cmd = "exec $cmd";
|
||||
sh::_fork_exec($cmd, $retcode);
|
||||
return $retcode == 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
namespace nur\sery\os\proc;
|
||||
|
||||
use nur\A;
|
||||
use nur\shell;
|
||||
|
||||
/**
|
||||
* Class AbstractCmdList: une séquence de commandes séparées par ;, && ou ||
|
||||
*/
|
||||
abstract class AbstractCmdList extends AbstractCmd {
|
||||
protected ?string $sep;
|
||||
|
||||
function __construct(?string $sep, $cmd=null, ?string $input=null, ?string $output=null) {
|
||||
parent::__construct();
|
||||
$this->sep = $sep;
|
||||
$this->add($cmd, $input, $output);
|
||||
}
|
||||
|
||||
function addLiteral($cmd): self {
|
||||
A::append_nn($this->cmds, $cmd);
|
||||
return $this;
|
||||
}
|
||||
|
||||
function add($cmd, ?string $input=null, ?string $output=null): self {
|
||||
if ($cmd !== null) {
|
||||
if (!($cmd instanceof ICmd)) {
|
||||
shell::fix_cmd($cmd, null, $input, $output);
|
||||
}
|
||||
$this->cmds[] = $cmd;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
function getCmd(?string $sep=null): string {
|
||||
if ($sep === null) $sep = "\n";
|
||||
|
||||
$actualCmd = [];
|
||||
A::append_nn($actualCmd, $this->getVars($sep));
|
||||
|
||||
$parts = [];
|
||||
foreach ($this->cmds as $cmd) {
|
||||
if ($cmd instanceof ICmd) {
|
||||
$cmd = "(".$cmd->getCmd($sep).")";
|
||||
}
|
||||
$parts[] = $cmd;
|
||||
}
|
||||
$psep = $this->sep;
|
||||
if ($psep === null) $psep = $sep;
|
||||
A::append($actualCmd, implode($psep, $parts));
|
||||
|
||||
return implode($sep, $actualCmd);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
namespace nur\sery\os\proc;
|
||||
|
||||
/**
|
||||
* Class CmdList: une séquence de commandes séparées par ;
|
||||
*
|
||||
* Toutes les commandes sont exécutées et le code d'erreur est celui de la
|
||||
* dernière commande exécutée
|
||||
*/
|
||||
class Cmd extends AbstractCmdList {
|
||||
static function with($cmd=null): Cmd {
|
||||
if ($cmd instanceof Cmd) return $cmd;
|
||||
return new static($cmd);
|
||||
}
|
||||
|
||||
function __construct($cmd=null, ?string $input=null, ?string $output=null) {
|
||||
parent::__construct(null, $cmd, $input, $output);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
namespace nur\sery\os\proc;
|
||||
|
||||
/**
|
||||
* Class CmdAnd: une séquence de commandes séparées par &&
|
||||
*
|
||||
* l'exécution s'arrête à la première erreur
|
||||
*/
|
||||
class CmdAnd extends AbstractCmdList {
|
||||
function __construct($cmd=null, ?string $input=null, ?string $output=null) {
|
||||
parent::__construct(" && ", $cmd, $input, $output);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
namespace nur\sery\os\proc;
|
||||
|
||||
/**
|
||||
* Class CmdOr: une séquence de commandes séparées par ||
|
||||
*
|
||||
* l'exécution s'arrête au premier succès
|
||||
*/
|
||||
class CmdOr extends AbstractCmdList {
|
||||
function __construct($cmd=null, ?string $input=null, ?string $output=null) {
|
||||
parent::__construct(" || ", $cmd, $input, $output);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
namespace nur\sery\os\proc;
|
||||
|
||||
use nur\A;
|
||||
use nur\shell;
|
||||
|
||||
/**
|
||||
* Class CmdPipe: une suite de commandes qui doivent s'exécuter avec les sorties
|
||||
* des unes connectées aux entrées des autres
|
||||
*/
|
||||
class CmdPipe extends AbstractCmd {
|
||||
private ?string $input;
|
||||
|
||||
private ?string $output;
|
||||
|
||||
function __construct(?array $cmds=null, ?string $input=null, ?string $output=null) {
|
||||
parent::__construct();
|
||||
if ($cmds !== null) {
|
||||
foreach ($cmds as $command) {
|
||||
$this->add($command);
|
||||
}
|
||||
}
|
||||
$this->input = $input;
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
function addLiteral($cmd): self {
|
||||
A::append_nn($this->cmds, $cmd);
|
||||
return $this;
|
||||
}
|
||||
|
||||
function add($cmd): self {
|
||||
if ($cmd !== null) {
|
||||
if (!($cmd instanceof ICmd)) {
|
||||
shell::fix_cmd($cmd);
|
||||
}
|
||||
$this->cmds[] = $cmd;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
function setInput(?string $input=null): self {
|
||||
$this->input = $input;
|
||||
return $this;
|
||||
}
|
||||
|
||||
function setOutput(?string $output=null): self {
|
||||
$this->output = $output;
|
||||
return $this;
|
||||
}
|
||||
|
||||
function getCmd(?string $sep=null): string {
|
||||
if ($sep === null) $sep = "\n";
|
||||
|
||||
$actualCmd = [];
|
||||
A::append_nn($actualCmd, $this->getVars($sep));
|
||||
|
||||
$parts = [];
|
||||
foreach ($this->cmds as $cmd) {
|
||||
if ($cmd instanceof ICmd) {
|
||||
$cmd = "(".$cmd->getCmd($sep).")";
|
||||
}
|
||||
$parts[] = $cmd;
|
||||
}
|
||||
$cmd = implode(" | ", $parts);
|
||||
|
||||
$input = $this->input;
|
||||
$output = $this->output;
|
||||
if ($input !== null || $output !== null) {
|
||||
$parts = [];
|
||||
if ($input !== null) $parts[] = "<".escapeshellarg($input);
|
||||
$parts[] = $cmd;
|
||||
if ($output !== null) $parts[] = ">".escapeshellarg($output);
|
||||
$cmd = implode(" ", $parts);
|
||||
}
|
||||
A::append($actualCmd, $cmd);
|
||||
|
||||
return implode($sep, $actualCmd);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
namespace nur\sery\os\proc;
|
||||
|
||||
/**
|
||||
* Interface ICmd: une abstraction d'une ou plusieurs commandes à lancer
|
||||
*/
|
||||
interface ICmd {
|
||||
/**
|
||||
* vérifier si cette commande a besoin que son entrée standard soit connectée
|
||||
* à un flux.
|
||||
*/
|
||||
function isNeedsStdin(): bool;
|
||||
|
||||
/**
|
||||
* vérifier si cette commande a besoin que sa sortie standard soit connectée
|
||||
* à un terminal
|
||||
*/
|
||||
function isNeedsTty(): bool;
|
||||
|
||||
/**
|
||||
* Ajouter le préfixe spécifié à la dernière commande de la liste
|
||||
*
|
||||
* si $prefix est un array, quoter puis assembler les éléments du tableau.
|
||||
* sinon ce doit être une chaine de caractère et elle est prise telle quelle
|
||||
*/
|
||||
function addPrefix($prefix): void;
|
||||
|
||||
/**
|
||||
* Ajouter des redirections à la dernière commande de la liste
|
||||
*
|
||||
* $redir spécifie le type de redirection demandée:
|
||||
* - "default" | null: $output reçoit STDOUT et STDERR n'est pas redirigé
|
||||
* - "outonly" | "noerr": $output ne reçoit que STDOUT et STDERR est perdu
|
||||
* - "erronly" | "noout": $output ne reçoit que STDERR et STDOUT est perdu
|
||||
* - "both" | "err2out": $output reçoit STDOUT et STDERR
|
||||
* - sinon c'est une redirection spécifique, et la valeur est rajoutée telle
|
||||
* quelle à la ligne de commande ($output est ignoré)
|
||||
*
|
||||
* $output est le nom d'un fichier qui reçoit les redirections, ou null pour
|
||||
* la valeur par défaut. spécifier $append==true pour ajouter au fichier
|
||||
* $output au lieu de l'écraser
|
||||
*/
|
||||
function addRedir(?string $redir, $output=null, bool $append=false, $input=null): void;
|
||||
|
||||
/** Obtenir le texte de la commande comme elle serait saisie dans un shell */
|
||||
function getCmd(?string $sep=null): string;
|
||||
|
||||
/**
|
||||
* Lancer la commande avec passthru() et retourner le code de retour dans la
|
||||
* variable $retcode
|
||||
*
|
||||
* voici la différence entre passthru(), system() et exec()
|
||||
* +----------------+-----------------+----------------+----------------+
|
||||
* | Command | Displays Output | Can Get Output | Gets Exit Code |
|
||||
* +----------------+-----------------+----------------+----------------+
|
||||
* | passthru() | Yes (raw) | No | Yes |
|
||||
* | system() | Yes (as text) | Last line only | Yes |
|
||||
* | exec() | No | Yes (array) | Yes |
|
||||
* +----------------+-----------------+----------------+----------------+
|
||||
*
|
||||
* @return bool true si la commande s'est lancée sans erreur, false sinon
|
||||
*/
|
||||
function passthru(int &$retcode=null): bool;
|
||||
|
||||
/**
|
||||
* Comme {@link passthru()} mais lancer la commande spécifiée avec system().
|
||||
* Cf la doc de {@link passthru()} pour les autres détails
|
||||
*/
|
||||
function system(string &$output=null, int &$retcode=null): bool;
|
||||
|
||||
/**
|
||||
* Comme {@link passthru()} mais lancer la commande spécifiée avec exec().
|
||||
* Cf la doc de {@link passthru()} pour les autres détails
|
||||
*/
|
||||
function exec(array &$output=null, int &$retcode=null): bool;
|
||||
|
||||
/**
|
||||
* Lancer la commande dans un processus fils via un shell et attendre la fin
|
||||
* de son exécution
|
||||
*/
|
||||
function fork_exec(int &$retcode=null): bool;
|
||||
}
|
Loading…
Reference in New Issue