mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +01:00
Modernize architecture of phd
Summary: Ref T1670. Mostly, use PhutilArgumentParser. This breaks up the mismash of functional stuff and PhabriatorDaemonControl into proper argumentparser Workflows. There are no functional changes, except that I removed the "pingConduit()" call prior to starting daemons, because I intend to remove all Conduit integration. Test Plan: - Ran `phd list`. - Ran `phd status` (running daemons). - Ran `phd status` (no running daemons). - Ran `phd stop <pid>` (dead task). - Ran `phd stop <pid>` (live task). - Ran `phd stop zebra` (invalid PID). - Ran `phd stop 1` (bad PID). - Ran `phd stop`. - Ran `phd debug zebra` (no match). - Ran `phd debug e` (ambiguous). - Ran `phd debug task`. - Ran `phd launch task`. - Ran `phd launch 0 task` (invalid arg). - Ran `phd launch 2 task`. - Ran `phd help`. - Ran `phd help list`. - Ran `phd start`. - Ran `phd restart`. - Looked at Repositories (daemon running). - Looked at Repositories (daemon not running). Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1670 Differential Revision: https://secure.phabricator.com/D6490
This commit is contained in:
parent
dd76143399
commit
d89b8ce2b2
11 changed files with 528 additions and 399 deletions
|
@ -4,183 +4,26 @@
|
||||||
$root = dirname(dirname(dirname(__FILE__)));
|
$root = dirname(dirname(dirname(__FILE__)));
|
||||||
require_once $root.'/scripts/__init_script__.php';
|
require_once $root.'/scripts/__init_script__.php';
|
||||||
|
|
||||||
$control = new PhabricatorDaemonControl();
|
PhabricatorDaemonManagementWorkflow::requireExtensions();
|
||||||
|
|
||||||
must_have_extension('pcntl');
|
$args = new PhutilArgumentParser($argv);
|
||||||
must_have_extension('posix');
|
$args->setTagline('manage daemons');
|
||||||
|
$args->setSynopsis(<<<EOSYNOPSIS
|
||||||
|
**phd** __command__ [__options__]
|
||||||
|
Manage Phabricator daeons.
|
||||||
|
|
||||||
function must_have_extension($ext) {
|
EOSYNOPSIS
|
||||||
if (!extension_loaded($ext)) {
|
|
||||||
echo "ERROR: The PHP extension '{$ext}' is not installed. You must ".
|
|
||||||
"install it to run daemons on this machine.\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$extension = new ReflectionExtension($ext);
|
|
||||||
foreach ($extension->getFunctions() as $function) {
|
|
||||||
$function = $function->name;
|
|
||||||
if (!function_exists($function)) {
|
|
||||||
echo "ERROR: The PHP function {$function}() is disabled. You must ".
|
|
||||||
"enable it to run daemons on this machine.\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$command = isset($argv[1]) ? $argv[1] : 'help';
|
|
||||||
switch ($command) {
|
|
||||||
case 'list':
|
|
||||||
$err = $control->executeListCommand();
|
|
||||||
exit($err);
|
|
||||||
|
|
||||||
case 'status':
|
|
||||||
$err = $control->executeStatusCommand();
|
|
||||||
exit($err);
|
|
||||||
|
|
||||||
case 'stop':
|
|
||||||
$pass_argv = array_slice($argv, 2);
|
|
||||||
$err = $control->executeStopCommand($pass_argv);
|
|
||||||
exit($err);
|
|
||||||
|
|
||||||
case 'restart':
|
|
||||||
$err = $control->executeStopCommand(array());
|
|
||||||
if ($err) {
|
|
||||||
exit($err);
|
|
||||||
}
|
|
||||||
/* Fall Through */
|
|
||||||
case 'start':
|
|
||||||
$running = $control->loadRunningDaemons();
|
|
||||||
// "running" might not mean actually running so much as was running at
|
|
||||||
// some point. ergo, do a quick grouping and only barf if daemons are
|
|
||||||
// *actually* running.
|
|
||||||
$running_dict = mgroup($running, 'isRunning');
|
|
||||||
if (!empty($running_dict[true])) {
|
|
||||||
echo phutil_console_wrap(
|
|
||||||
"phd start: Unable to start daemons because daemons are already ".
|
|
||||||
"running.\n".
|
|
||||||
"You can view running daemons with 'phd status'.\n".
|
|
||||||
"You can stop running daemons with 'phd stop'.\n".
|
|
||||||
"You can use 'phd restart' to stop all daemons before starting new ".
|
|
||||||
"daemons.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$daemons = array(
|
|
||||||
array('PhabricatorRepositoryPullLocalDaemon', array()),
|
|
||||||
array('PhabricatorGarbageCollectorDaemon', array()),
|
|
||||||
);
|
);
|
||||||
|
$args->parseStandardArguments();
|
||||||
|
$workflows = array(
|
||||||
|
new PhabricatorDaemonManagementListWorkflow(),
|
||||||
|
new PhabricatorDaemonManagementStatusWorkflow(),
|
||||||
|
new PhabricatorDaemonManagementStartWorkflow(),
|
||||||
|
new PhabricatorDaemonManagementStopWorkflow(),
|
||||||
|
new PhabricatorDaemonManagementRestartWorkflow(),
|
||||||
|
new PhabricatorDaemonManagementLaunchWorkflow(),
|
||||||
|
new PhabricatorDaemonManagementDebugWorkflow(),
|
||||||
|
new PhutilHelpArgumentWorkflow(),
|
||||||
|
);
|
||||||
|
|
||||||
$taskmasters = PhabricatorEnv::getEnvConfig('phd.start-taskmasters');
|
$args->parseWorkflows($workflows);
|
||||||
for ($ii = 0; $ii < $taskmasters; $ii++) {
|
|
||||||
$daemons[] = array('PhabricatorTaskmasterDaemon', array());
|
|
||||||
}
|
|
||||||
|
|
||||||
will_launch($control);
|
|
||||||
foreach ($daemons as $spec) {
|
|
||||||
list($name, $argv) = $spec;
|
|
||||||
echo "Launching '{$name}'...\n";
|
|
||||||
$control->launchDaemon($name, $argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Done.\n";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'launch':
|
|
||||||
case 'debug':
|
|
||||||
$is_debug = ($argv[1] == 'debug');
|
|
||||||
|
|
||||||
$daemon = idx($argv, 2);
|
|
||||||
if (!$daemon) {
|
|
||||||
throw new Exception("Daemon name required!");
|
|
||||||
}
|
|
||||||
|
|
||||||
$pass_argv = array_slice($argv, 3);
|
|
||||||
|
|
||||||
$n = 1;
|
|
||||||
if (!$is_debug) {
|
|
||||||
if (is_numeric($daemon)) {
|
|
||||||
$n = $daemon;
|
|
||||||
if ($n < 1) {
|
|
||||||
throw new Exception("Count must be at least 1!");
|
|
||||||
}
|
|
||||||
$daemon = idx($argv, 3);
|
|
||||||
if (!$daemon) {
|
|
||||||
throw new Exception("Daemon name required!");
|
|
||||||
}
|
|
||||||
$pass_argv = array_slice($argv, 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$loader = new PhutilSymbolLoader();
|
|
||||||
$symbols = $loader
|
|
||||||
->setAncestorClass('PhutilDaemon')
|
|
||||||
->selectSymbolsWithoutLoading();
|
|
||||||
|
|
||||||
$symbols = ipull($symbols, 'name');
|
|
||||||
$match = array();
|
|
||||||
foreach ($symbols as $symbol) {
|
|
||||||
if (stripos($symbol, $daemon) !== false) {
|
|
||||||
if (strtolower($symbol) == strtolower($daemon)) {
|
|
||||||
$match = array($symbol);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
$match[] = $symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count($match) == 0) {
|
|
||||||
throw new Exception(
|
|
||||||
"No daemons match! Use 'phd list' for a list of daemons.");
|
|
||||||
} else if (count($match) > 1) {
|
|
||||||
throw new Exception(
|
|
||||||
"Which of these daemons did you mean?\n".
|
|
||||||
" ".implode("\n ", $match));
|
|
||||||
} else {
|
|
||||||
$daemon = reset($match);
|
|
||||||
}
|
|
||||||
|
|
||||||
$with_logs = true;
|
|
||||||
if ($is_debug) {
|
|
||||||
// In debug mode, we emit errors straight to stdout, so nothing useful
|
|
||||||
// will show up in the logs. Don't echo the message about stuff showing
|
|
||||||
// up in them, since it would be confusing.
|
|
||||||
$with_logs = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
will_launch($control, $with_logs);
|
|
||||||
|
|
||||||
if ($is_debug) {
|
|
||||||
echo "Launching {$daemon} in debug mode (nondaemonized)...\n";
|
|
||||||
} else {
|
|
||||||
echo "Launching {$n} x {$daemon}";
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($ii = 0; $ii < $n; $ii++) {
|
|
||||||
$control->launchDaemon($daemon, $pass_argv, $is_debug);
|
|
||||||
if (!$is_debug) {
|
|
||||||
echo ".";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "\n";
|
|
||||||
echo "Done.\n";
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '--help':
|
|
||||||
case 'help':
|
|
||||||
default:
|
|
||||||
$err = $control->executeHelpCommand();
|
|
||||||
exit($err);
|
|
||||||
}
|
|
||||||
|
|
||||||
function will_launch($control, $with_logs = true) {
|
|
||||||
echo "Staging launch...\n";
|
|
||||||
$control->pingConduit();
|
|
||||||
if ($with_logs) {
|
|
||||||
$log_dir = $control->getLogDirectory().'/daemons.log';
|
|
||||||
echo "NOTE: Logs will appear in '{$log_dir}'.\n\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1016,7 +1016,6 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorDaemon' => 'infrastructure/daemon/PhabricatorDaemon.php',
|
'PhabricatorDaemon' => 'infrastructure/daemon/PhabricatorDaemon.php',
|
||||||
'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/PhabricatorDaemonCombinedLogController.php',
|
'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/PhabricatorDaemonCombinedLogController.php',
|
||||||
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/PhabricatorDaemonConsoleController.php',
|
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/PhabricatorDaemonConsoleController.php',
|
||||||
'PhabricatorDaemonControl' => 'infrastructure/daemon/PhabricatorDaemonControl.php',
|
|
||||||
'PhabricatorDaemonController' => 'applications/daemon/controller/PhabricatorDaemonController.php',
|
'PhabricatorDaemonController' => 'applications/daemon/controller/PhabricatorDaemonController.php',
|
||||||
'PhabricatorDaemonDAO' => 'infrastructure/daemon/storage/PhabricatorDaemonDAO.php',
|
'PhabricatorDaemonDAO' => 'infrastructure/daemon/storage/PhabricatorDaemonDAO.php',
|
||||||
'PhabricatorDaemonLog' => 'infrastructure/daemon/storage/PhabricatorDaemonLog.php',
|
'PhabricatorDaemonLog' => 'infrastructure/daemon/storage/PhabricatorDaemonLog.php',
|
||||||
|
@ -1025,6 +1024,14 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorDaemonLogListController' => 'applications/daemon/controller/PhabricatorDaemonLogListController.php',
|
'PhabricatorDaemonLogListController' => 'applications/daemon/controller/PhabricatorDaemonLogListController.php',
|
||||||
'PhabricatorDaemonLogListView' => 'applications/daemon/view/PhabricatorDaemonLogListView.php',
|
'PhabricatorDaemonLogListView' => 'applications/daemon/view/PhabricatorDaemonLogListView.php',
|
||||||
'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/PhabricatorDaemonLogViewController.php',
|
'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/PhabricatorDaemonLogViewController.php',
|
||||||
|
'PhabricatorDaemonManagementDebugWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementDebugWorkflow.php',
|
||||||
|
'PhabricatorDaemonManagementLaunchWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementLaunchWorkflow.php',
|
||||||
|
'PhabricatorDaemonManagementListWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementListWorkflow.php',
|
||||||
|
'PhabricatorDaemonManagementRestartWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementRestartWorkflow.php',
|
||||||
|
'PhabricatorDaemonManagementStartWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStartWorkflow.php',
|
||||||
|
'PhabricatorDaemonManagementStatusWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php',
|
||||||
|
'PhabricatorDaemonManagementStopWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementStopWorkflow.php',
|
||||||
|
'PhabricatorDaemonManagementWorkflow' => 'applications/daemon/management/PhabricatorDaemonManagementWorkflow.php',
|
||||||
'PhabricatorDaemonReference' => 'infrastructure/daemon/control/PhabricatorDaemonReference.php',
|
'PhabricatorDaemonReference' => 'infrastructure/daemon/control/PhabricatorDaemonReference.php',
|
||||||
'PhabricatorDebugController' => 'applications/system/PhabricatorDebugController.php',
|
'PhabricatorDebugController' => 'applications/system/PhabricatorDebugController.php',
|
||||||
'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorDefaultFileStorageEngineSelector.php',
|
'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorDefaultFileStorageEngineSelector.php',
|
||||||
|
@ -2991,6 +2998,14 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController',
|
'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController',
|
||||||
'PhabricatorDaemonLogListView' => 'AphrontView',
|
'PhabricatorDaemonLogListView' => 'AphrontView',
|
||||||
'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController',
|
'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController',
|
||||||
|
'PhabricatorDaemonManagementDebugWorkflow' => 'PhabricatorDaemonManagementWorkflow',
|
||||||
|
'PhabricatorDaemonManagementLaunchWorkflow' => 'PhabricatorDaemonManagementWorkflow',
|
||||||
|
'PhabricatorDaemonManagementListWorkflow' => 'PhabricatorDaemonManagementWorkflow',
|
||||||
|
'PhabricatorDaemonManagementRestartWorkflow' => 'PhabricatorDaemonManagementWorkflow',
|
||||||
|
'PhabricatorDaemonManagementStartWorkflow' => 'PhabricatorDaemonManagementWorkflow',
|
||||||
|
'PhabricatorDaemonManagementStatusWorkflow' => 'PhabricatorDaemonManagementWorkflow',
|
||||||
|
'PhabricatorDaemonManagementStopWorkflow' => 'PhabricatorDaemonManagementWorkflow',
|
||||||
|
'PhabricatorDaemonManagementWorkflow' => 'PhutilArgumentWorkflow',
|
||||||
'PhabricatorDebugController' => 'PhabricatorController',
|
'PhabricatorDebugController' => 'PhabricatorController',
|
||||||
'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector',
|
'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector',
|
||||||
'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector',
|
'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector',
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorDaemonManagementDebugWorkflow
|
||||||
|
extends PhabricatorDaemonManagementWorkflow {
|
||||||
|
|
||||||
|
public function shouldParsePartial() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('debug')
|
||||||
|
->setSynopsis(pht('Show a list of available daemons.'))
|
||||||
|
->setArguments(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'name' => 'argv',
|
||||||
|
'wildcard' => true,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
$argv = $args->getArg('argv');
|
||||||
|
|
||||||
|
if (!$argv) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht('You must specify which daemon to debug.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$daemon_class = array_shift($argv);
|
||||||
|
return $this->launchDaemon($daemon_class, $argv, $is_debug = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorDaemonManagementLaunchWorkflow
|
||||||
|
extends PhabricatorDaemonManagementWorkflow {
|
||||||
|
|
||||||
|
public function shouldParsePartial() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('launch')
|
||||||
|
->setSynopsis(pht('Show a list of available daemons.'))
|
||||||
|
->setArguments(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'name' => 'argv',
|
||||||
|
'wildcard' => true,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
$argv = $args->getArg('argv');
|
||||||
|
|
||||||
|
$daemon_count = 1;
|
||||||
|
if ($argv) {
|
||||||
|
if (is_numeric(head($argv))) {
|
||||||
|
$daemon_count = array_shift($argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($daemon_count < 1) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht('You must launch at least one daemon.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$argv) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht('You must specify which daemon to launch.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$daemon_class = array_shift($argv);
|
||||||
|
|
||||||
|
$this->willLaunchDaemons();
|
||||||
|
|
||||||
|
for ($ii = 0; $ii < $daemon_count; $ii++) {
|
||||||
|
$this->launchDaemon($daemon_class, $argv, $is_debug = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorDaemonManagementListWorkflow
|
||||||
|
extends PhabricatorDaemonManagementWorkflow {
|
||||||
|
|
||||||
|
public function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('list')
|
||||||
|
->setSynopsis(pht('Show a list of available daemons.'))
|
||||||
|
->setArguments(array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
|
||||||
|
$symbols = $this->loadAvailableDaemonClasses();
|
||||||
|
$symbols = igroup($symbols, 'library');
|
||||||
|
|
||||||
|
foreach ($symbols as $library => $symbol_list) {
|
||||||
|
$console->writeOut(pht("Daemons in library __%s__:", $library)."\n");
|
||||||
|
foreach ($symbol_list as $symbol) {
|
||||||
|
$console->writeOut(" %s\n", $symbol['name']);
|
||||||
|
}
|
||||||
|
$console->writeOut("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorDaemonManagementRestartWorkflow
|
||||||
|
extends PhabricatorDaemonManagementWorkflow {
|
||||||
|
|
||||||
|
public function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('restart')
|
||||||
|
->setSynopsis(
|
||||||
|
pht(
|
||||||
|
'Stop, then start the standard daemon loadout.'))
|
||||||
|
->setArguments(array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
$err = $this->executeStopCommand(array());
|
||||||
|
if ($err) {
|
||||||
|
return $err;
|
||||||
|
}
|
||||||
|
return $this->executeStartCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorDaemonManagementStartWorkflow
|
||||||
|
extends PhabricatorDaemonManagementWorkflow {
|
||||||
|
|
||||||
|
public function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('start')
|
||||||
|
->setSynopsis(
|
||||||
|
pht(
|
||||||
|
'Start the standard configured collection of Phabricator daemons. '.
|
||||||
|
'This is appropriate for most installs. Use **phd launch** to '.
|
||||||
|
'customize which daemons are launched.'))
|
||||||
|
->setArguments(array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
return $this->executeStartCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorDaemonManagementStatusWorkflow
|
||||||
|
extends PhabricatorDaemonManagementWorkflow {
|
||||||
|
|
||||||
|
public function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('status')
|
||||||
|
->setSynopsis(pht('Show status of running daemons.'))
|
||||||
|
->setArguments(array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
$daemons = $this->loadRunningDaemons();
|
||||||
|
|
||||||
|
if (!$daemons) {
|
||||||
|
$console->writeErr(
|
||||||
|
"%s\n",
|
||||||
|
pht("There are no running Phabricator daemons."));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = 0;
|
||||||
|
printf(
|
||||||
|
"%-5s\t%-24s\t%s\n",
|
||||||
|
"PID",
|
||||||
|
"Started",
|
||||||
|
"Daemon");
|
||||||
|
foreach ($daemons as $daemon) {
|
||||||
|
$name = $daemon->getName();
|
||||||
|
if (!$daemon->isRunning()) {
|
||||||
|
$daemon->updateStatus(PhabricatorDaemonLog::STATUS_DEAD);
|
||||||
|
$status = 2;
|
||||||
|
$name = '<DEAD> '.$name;
|
||||||
|
}
|
||||||
|
printf(
|
||||||
|
"%5s\t%-24s\t%s\n",
|
||||||
|
$daemon->getPID(),
|
||||||
|
$daemon->getEpochStarted()
|
||||||
|
? date('M j Y, g:i:s A', $daemon->getEpochStarted())
|
||||||
|
: null,
|
||||||
|
$name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorDaemonManagementStopWorkflow
|
||||||
|
extends PhabricatorDaemonManagementWorkflow {
|
||||||
|
|
||||||
|
public function didConstruct() {
|
||||||
|
$this
|
||||||
|
->setName('stop')
|
||||||
|
->setSynopsis(
|
||||||
|
pht(
|
||||||
|
'Stop all running daemons, or specific daemons identified by PIDs. '.
|
||||||
|
'Use **phd status** to find PIDs.'))
|
||||||
|
->setArguments(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'name' => 'pids',
|
||||||
|
'wildcard' => true,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PhutilArgumentParser $args) {
|
||||||
|
$pids = $args->getArg('pids');
|
||||||
|
return $this->executeStopCommand($pids);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,195 +1,118 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class PhabricatorDaemonControl {
|
abstract class PhabricatorDaemonManagementWorkflow
|
||||||
|
extends PhutilArgumentWorkflow {
|
||||||
|
|
||||||
|
public function isExecutable() {
|
||||||
public function executeListCommand() {
|
return true;
|
||||||
$symbols = $this->loadAvailableDaemonClasses();
|
|
||||||
|
|
||||||
$symbols = igroup($symbols, 'library');
|
|
||||||
|
|
||||||
echo "\n";
|
|
||||||
foreach ($symbols as $library => $symbol_list) {
|
|
||||||
echo phutil_console_format("Daemons in library __%s__:\n", $library);
|
|
||||||
foreach ($symbol_list as $symbol) {
|
|
||||||
echo " ".$symbol['name']."\n";
|
|
||||||
}
|
|
||||||
echo "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
protected function loadAvailableDaemonClasses() {
|
||||||
|
$loader = new PhutilSymbolLoader();
|
||||||
|
return $loader
|
||||||
|
->setAncestorClass('PhutilDaemon')
|
||||||
|
->setConcreteOnly(true)
|
||||||
|
->selectSymbolsWithoutLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function executeStatusCommand() {
|
public function getPIDDirectory() {
|
||||||
$daemons = $this->loadRunningDaemons();
|
$path = PhabricatorEnv::getEnvConfig('phd.pid-directory');
|
||||||
|
return $this->getControlDirectory($path);
|
||||||
if (!$daemons) {
|
|
||||||
echo "There are no running Phabricator daemons.\n";
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$status = 0;
|
public function getLogDirectory() {
|
||||||
printf(
|
$path = PhabricatorEnv::getEnvConfig('phd.log-directory');
|
||||||
"%-5s\t%-24s\t%s\n",
|
return $this->getControlDirectory($path);
|
||||||
"PID",
|
|
||||||
"Started",
|
|
||||||
"Daemon");
|
|
||||||
foreach ($daemons as $daemon) {
|
|
||||||
$name = $daemon->getName();
|
|
||||||
if (!$daemon->isRunning()) {
|
|
||||||
$daemon->updateStatus(PhabricatorDaemonLog::STATUS_DEAD);
|
|
||||||
$status = 2;
|
|
||||||
$name = '<DEAD> '.$name;
|
|
||||||
}
|
|
||||||
printf(
|
|
||||||
"%5s\t%-24s\t%s\n",
|
|
||||||
$daemon->getPID(),
|
|
||||||
$daemon->getEpochStarted()
|
|
||||||
? date('M j Y, g:i:s A', $daemon->getEpochStarted())
|
|
||||||
: null,
|
|
||||||
$name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $status;
|
private function getControlDirectory($path) {
|
||||||
}
|
if (!Filesystem::pathExists($path)) {
|
||||||
|
list($err) = exec_manual('mkdir -p %s', $path);
|
||||||
public function executeStopCommand($pids = null) {
|
if ($err) {
|
||||||
$daemons = $this->loadRunningDaemons();
|
|
||||||
if (!$daemons) {
|
|
||||||
echo "There are no running Phabricator daemons.\n";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$daemons = mpull($daemons, null, 'getPID');
|
|
||||||
|
|
||||||
$running = array();
|
|
||||||
if ($pids == null) {
|
|
||||||
$running = $daemons;
|
|
||||||
} else {
|
|
||||||
// We were given a PID or set of PIDs to kill.
|
|
||||||
foreach ($pids as $key => $pid) {
|
|
||||||
if (!preg_match('/^\d+$/', $pid)) {
|
|
||||||
echo "'{$pid}' is not a valid PID.\n";
|
|
||||||
continue;
|
|
||||||
} else if (empty($daemons[$pid])) {
|
|
||||||
echo "'{$pid}' is not Phabricator-controlled PID. Not killing.\n";
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
$running[] = $daemons[$pid];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($running)) {
|
|
||||||
echo "No daemons to kill.\n";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$all_daemons = $running;
|
|
||||||
|
|
||||||
foreach ($running as $key => $daemon) {
|
|
||||||
$pid = $daemon->getPID();
|
|
||||||
$name = $daemon->getName();
|
|
||||||
|
|
||||||
echo "Stopping daemon '{$name}' ({$pid})...\n";
|
|
||||||
if (!$daemon->isRunning()) {
|
|
||||||
echo "Daemon is not running.\n";
|
|
||||||
unset($running[$key]);
|
|
||||||
$daemon->updateStatus(PhabricatorDaemonLog::STATUS_EXITED);
|
|
||||||
} else {
|
|
||||||
posix_kill($pid, SIGINT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$start = time();
|
|
||||||
do {
|
|
||||||
foreach ($running as $key => $daemon) {
|
|
||||||
$pid = $daemon->getPID();
|
|
||||||
if (!$daemon->isRunning()) {
|
|
||||||
echo "Daemon {$pid} exited normally.\n";
|
|
||||||
unset($running[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (empty($running)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
usleep(100000);
|
|
||||||
} while (time() < $start + 15);
|
|
||||||
|
|
||||||
foreach ($running as $key => $daemon) {
|
|
||||||
$pid = $daemon->getPID();
|
|
||||||
echo "KILLing daemon {$pid}.\n";
|
|
||||||
posix_kill($pid, SIGKILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($all_daemons as $daemon) {
|
|
||||||
if ($daemon->getPIDFile()) {
|
|
||||||
Filesystem::remove($daemon->getPIDFile());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function executeHelpCommand() {
|
|
||||||
echo phutil_console_format(<<<EOHELP
|
|
||||||
**NAME**
|
|
||||||
**phd** - phabricator daemon launcher
|
|
||||||
|
|
||||||
**COMMAND REFERENCE**
|
|
||||||
|
|
||||||
**start**
|
|
||||||
Start the normal collection of daemons that Phabricator uses. This
|
|
||||||
is appropriate for most installs. If you want to customize what
|
|
||||||
is launched, you can use **launch** for fine-grained control.
|
|
||||||
|
|
||||||
**restart**
|
|
||||||
Stop all running daemons, then start a standard loadout.
|
|
||||||
|
|
||||||
**stop** [PID ...]
|
|
||||||
Stop all running daemons if no PIDs are given, or a particular
|
|
||||||
PID or set of PIDs, if they are supplied.
|
|
||||||
|
|
||||||
**launch** [__n__] __daemon__ [argv ...]
|
|
||||||
**debug** __daemon__ [argv ...]
|
|
||||||
Start a daemon (or n copies of a daemon).
|
|
||||||
With **debug**, do not daemonize. Use this if you're having trouble
|
|
||||||
getting daemons working.
|
|
||||||
|
|
||||||
**list**
|
|
||||||
List available daemons.
|
|
||||||
|
|
||||||
**status**
|
|
||||||
List running daemons. This command will exit with a non-zero exit
|
|
||||||
status if any daemons are not running.
|
|
||||||
|
|
||||||
**help**
|
|
||||||
Show this help.
|
|
||||||
|
|
||||||
EOHELP
|
|
||||||
);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pingConduit() {
|
|
||||||
// It's fairly common to have issues here, e.g. because Phabricator isn't
|
|
||||||
// running, isn't accessible, you put the domain in your hostsfile but it
|
|
||||||
// isn't available on the production host, etc. If any of this doesn't work,
|
|
||||||
// conduit will throw.
|
|
||||||
|
|
||||||
$conduit = new ConduitClient(PhabricatorEnv::getURI('/api/'));
|
|
||||||
$conduit->callMethodSynchronous('conduit.ping', array());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function launchDaemon($daemon, array $argv, $debug = false) {
|
|
||||||
$symbols = $this->loadAvailableDaemonClasses();
|
|
||||||
$symbols = ipull($symbols, 'name', 'name');
|
|
||||||
if (empty($symbols[$daemon])) {
|
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Daemon '{$daemon}' is not loaded, misspelled or abstract.");
|
"phd requires the directory '{$path}' to exist, but it does not ".
|
||||||
|
"exist and could not be created. Create this directory or update ".
|
||||||
|
"'phd.pid-directory' / 'phd.log-directory' in your configuration ".
|
||||||
|
"to point to an existing directory.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $path;
|
||||||
}
|
}
|
||||||
|
|
||||||
$libphutil_root = dirname(phutil_get_library_root('phutil'));
|
public function loadRunningDaemons() {
|
||||||
$launch_daemon = $libphutil_root.'/scripts/daemon/';
|
$results = array();
|
||||||
|
|
||||||
|
$pid_dir = $this->getPIDDirectory();
|
||||||
|
$pid_files = Filesystem::listDirectory($pid_dir);
|
||||||
|
if (!$pid_files) {
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($pid_files as $pid_file) {
|
||||||
|
$pid_data = Filesystem::readFile($pid_dir.'/'.$pid_file);
|
||||||
|
$dict = json_decode($pid_data, true);
|
||||||
|
if (!is_array($dict)) {
|
||||||
|
// Just return a hanging reference, since control code needs to be
|
||||||
|
// robust against unusual system states.
|
||||||
|
$dict = array();
|
||||||
|
}
|
||||||
|
$ref = PhabricatorDaemonReference::newFromDictionary($dict);
|
||||||
|
$ref->setPIDFile($pid_dir.'/'.$pid_file);
|
||||||
|
$results[] = $ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function findDaemonClass($substring) {
|
||||||
|
$symbols = $this->loadAvailableDaemonClasses();
|
||||||
|
|
||||||
|
$symbols = ipull($symbols, 'name');
|
||||||
|
$match = array();
|
||||||
|
foreach ($symbols as $symbol) {
|
||||||
|
if (stripos($symbol, $substring) !== false) {
|
||||||
|
if (strtolower($symbol) == strtolower($substring)) {
|
||||||
|
$match = array($symbol);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$match[] = $symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($match) == 0) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
"No daemons match '%s'! Use 'phd list' for a list of avialable ".
|
||||||
|
"daemons.",
|
||||||
|
$substring));
|
||||||
|
} else if (count($match) > 1) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
"Specify a daemon unambiguously. Multiple daemons match '%s': %s.",
|
||||||
|
$substring,
|
||||||
|
implode(', ', $match)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return head($match);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function launchDaemon($class, array $argv, $debug) {
|
||||||
|
$daemon = $this->findDaemonClass($class);
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
|
||||||
|
if ($debug) {
|
||||||
|
$console->writeOut(
|
||||||
|
pht(
|
||||||
|
'Launching daemon "%s" in debug mode (not daemonized).',
|
||||||
|
$daemon)."\n");
|
||||||
|
} else {
|
||||||
|
$console->writeOut(
|
||||||
|
pht(
|
||||||
|
'Launching daemon "%s".',
|
||||||
|
$daemon)."\n");
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($argv as $key => $arg) {
|
foreach ($argv as $key => $arg) {
|
||||||
$argv[$key] = escapeshellarg($arg);
|
$argv[$key] = escapeshellarg($arg);
|
||||||
|
@ -242,20 +165,23 @@ EOHELP
|
||||||
implode(' ', $flags),
|
implode(' ', $flags),
|
||||||
implode(' ', $argv));
|
implode(' ', $argv));
|
||||||
|
|
||||||
|
$libphutil_root = dirname(phutil_get_library_root('phutil'));
|
||||||
|
$daemon_script_dir = $libphutil_root.'/scripts/daemon/';
|
||||||
|
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
// Don't terminate when the user sends ^C; it will be sent to the
|
// Don't terminate when the user sends ^C; it will be sent to the
|
||||||
// subprocess which will terminate normally.
|
// subprocess which will terminate normally.
|
||||||
pcntl_signal(
|
pcntl_signal(
|
||||||
SIGINT,
|
SIGINT,
|
||||||
array('PhabricatorDaemonControl', 'ignoreSignal'));
|
array(__CLASS__, 'ignoreSignal'));
|
||||||
|
|
||||||
echo "\n libphutil/scripts/daemon/ \$ {$command}\n\n";
|
echo "\n libphutil/scripts/daemon/ \$ {$command}\n\n";
|
||||||
|
|
||||||
phutil_passthru('(cd %s && exec %C)', $launch_daemon, $command);
|
phutil_passthru('(cd %s && exec %C)', $daemon_script_dir, $command);
|
||||||
} else {
|
} else {
|
||||||
$future = new ExecFuture('exec %C', $command);
|
$future = new ExecFuture('exec %C', $command);
|
||||||
// Play games to keep 'ps' looking reasonable.
|
// Play games to keep 'ps' looking reasonable.
|
||||||
$future->setCWD($launch_daemon);
|
$future->setCWD($daemon_script_dir);
|
||||||
$future->resolvex();
|
$future->resolvex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,64 +190,167 @@ EOHELP
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getControlDirectory($path) {
|
public static function requireExtensions() {
|
||||||
if (!Filesystem::pathExists($path)) {
|
self::mustHaveExtension('pcntl');
|
||||||
list($err) = exec_manual('mkdir -p %s', $path);
|
self::mustHaveExtension('posix');
|
||||||
if ($err) {
|
|
||||||
throw new Exception(
|
|
||||||
"phd requires the directory '{$path}' to exist, but it does not ".
|
|
||||||
"exist and could not be created. Create this directory or update ".
|
|
||||||
"'phd.pid-directory' / 'phd.log-directory' in your configuration ".
|
|
||||||
"to point to an existing directory.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPIDDirectory() {
|
private static function mustHaveExtension($ext) {
|
||||||
$path = PhabricatorEnv::getEnvConfig('phd.pid-directory');
|
if (!extension_loaded($ext)) {
|
||||||
return $this->getControlDirectory($path);
|
echo "ERROR: The PHP extension '{$ext}' is not installed. You must ".
|
||||||
|
"install it to run daemons on this machine.\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLogDirectory() {
|
$extension = new ReflectionExtension($ext);
|
||||||
$path = PhabricatorEnv::getEnvConfig('phd.log-directory');
|
foreach ($extension->getFunctions() as $function) {
|
||||||
return $this->getControlDirectory($path);
|
$function = $function->name;
|
||||||
|
if (!function_exists($function)) {
|
||||||
|
echo "ERROR: The PHP function {$function}() is disabled. You must ".
|
||||||
|
"enable it to run daemons on this machine.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadAvailableDaemonClasses() {
|
protected function willLaunchDaemons() {
|
||||||
$loader = new PhutilSymbolLoader();
|
$console = PhutilConsole::getConsole();
|
||||||
return $loader
|
$console->writeErr(pht('Preparing to launch daemons.')."\n");
|
||||||
->setAncestorClass('PhutilDaemon')
|
|
||||||
->setConcreteOnly(true)
|
$log_dir = $this->getLogDirectory().'/daemons.log';
|
||||||
->selectSymbolsWithoutLoading();
|
$console->writeErr(pht("NOTE: Logs will appear in '%s'.", $log_dir)."\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadRunningDaemons() {
|
|
||||||
$results = array();
|
|
||||||
|
|
||||||
$pid_dir = $this->getPIDDirectory();
|
/* -( Commands )----------------------------------------------------------- */
|
||||||
$pid_files = Filesystem::listDirectory($pid_dir);
|
|
||||||
if (!$pid_files) {
|
|
||||||
return $results;
|
protected function executeStartCommand() {
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
|
||||||
|
$running = $this->loadRunningDaemons();
|
||||||
|
|
||||||
|
// This may include daemons which were launched but which are no longer
|
||||||
|
// running; check that we actually have active daemons before failing.
|
||||||
|
foreach ($running as $daemon) {
|
||||||
|
if ($daemon->isRunning()) {
|
||||||
|
$message = pht(
|
||||||
|
"phd start: Unable to start daemons because daemons are already ".
|
||||||
|
"running.\n".
|
||||||
|
"You can view running daemons with 'phd status'.\n".
|
||||||
|
"You can stop running daemons with 'phd stop'.\n".
|
||||||
|
"You can use 'phd restart' to stop all daemons before starting new ".
|
||||||
|
"daemons.");
|
||||||
|
|
||||||
|
$console->writeErr("%s\n", $message);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($pid_files as $pid_file) {
|
$daemons = array(
|
||||||
$pid_data = Filesystem::readFile($pid_dir.'/'.$pid_file);
|
array('PhabricatorRepositoryPullLocalDaemon', array()),
|
||||||
$dict = json_decode($pid_data, true);
|
array('PhabricatorGarbageCollectorDaemon', array()),
|
||||||
if (!is_array($dict)) {
|
);
|
||||||
// Just return a hanging reference, since control code needs to be
|
|
||||||
// robust against unusual system states.
|
$taskmasters = PhabricatorEnv::getEnvConfig('phd.start-taskmasters');
|
||||||
$dict = array();
|
for ($ii = 0; $ii < $taskmasters; $ii++) {
|
||||||
}
|
$daemons[] = array('PhabricatorTaskmasterDaemon', array());
|
||||||
$ref = PhabricatorDaemonReference::newFromDictionary($dict);
|
|
||||||
$ref->setPIDFile($pid_dir.'/'.$pid_file);
|
|
||||||
$results[] = $ref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $results;
|
$this->willLaunchDaemons();
|
||||||
|
|
||||||
|
foreach ($daemons as $spec) {
|
||||||
|
list($name, $argv) = $spec;
|
||||||
|
$this->launchDaemon($name, $argv, $is_debug = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function killDaemon(PhabricatorDaemonReference $ref) {
|
$console->writeErr(pht("Done.")."\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected function executeStopCommand(array $pids) {
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
|
||||||
|
$daemons = $this->loadRunningDaemons();
|
||||||
|
if (!$daemons) {
|
||||||
|
$console->writeErr(pht('There are no running Phabricator daemons.')."\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$daemons = mpull($daemons, null, 'getPID');
|
||||||
|
|
||||||
|
$running = array();
|
||||||
|
if (!$pids) {
|
||||||
|
$running = $daemons;
|
||||||
|
} else {
|
||||||
|
// We were given a PID or set of PIDs to kill.
|
||||||
|
foreach ($pids as $key => $pid) {
|
||||||
|
if (!preg_match('/^\d+$/', $pid)) {
|
||||||
|
$console->writeErr(pht("PID '%s' is not a valid PID.", $pid)."\n");
|
||||||
|
continue;
|
||||||
|
} else if (empty($daemons[$pid])) {
|
||||||
|
$console->writeErr(
|
||||||
|
pht(
|
||||||
|
"PID '%s' is not a Phabricator daemon PID. It will not ".
|
||||||
|
"be killed.",
|
||||||
|
$pid)."\n");
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
$running[] = $daemons[$pid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($running)) {
|
||||||
|
$console->writeErr(pht("No daemons to kill.")."\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$all_daemons = $running;
|
||||||
|
foreach ($running as $key => $daemon) {
|
||||||
|
$pid = $daemon->getPID();
|
||||||
|
$name = $daemon->getName();
|
||||||
|
|
||||||
|
$console->writeErr(pht("Stopping daemon '%s' (%s)...", $name, $pid)."\n");
|
||||||
|
if (!$daemon->isRunning()) {
|
||||||
|
$console->writeErr(pht("Daemon is not running.")."\n");
|
||||||
|
unset($running[$key]);
|
||||||
|
$daemon->updateStatus(PhabricatorDaemonLog::STATUS_EXITED);
|
||||||
|
} else {
|
||||||
|
posix_kill($pid, SIGINT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$start = time();
|
||||||
|
do {
|
||||||
|
foreach ($running as $key => $daemon) {
|
||||||
|
$pid = $daemon->getPID();
|
||||||
|
if (!$daemon->isRunning()) {
|
||||||
|
$console->writeOut(pht('Daemon %s exited normally.', $pid)."\n");
|
||||||
|
unset($running[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (empty($running)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
usleep(100000);
|
||||||
|
} while (time() < $start + 15);
|
||||||
|
|
||||||
|
foreach ($running as $key => $daemon) {
|
||||||
|
$pid = $daemon->getPID();
|
||||||
|
$console->writeErr(pht('Sending daemon %s a SIGKILL.', $pid)."\n");
|
||||||
|
posix_kill($pid, SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($all_daemons as $daemon) {
|
||||||
|
if ($daemon->getPIDFile()) {
|
||||||
|
Filesystem::remove($daemon->getPIDFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,7 +22,8 @@ abstract class PhabricatorRepositoryController extends PhabricatorController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isPullDaemonRunning() {
|
private function isPullDaemonRunning() {
|
||||||
$control = new PhabricatorDaemonControl();
|
// TODO: This is yuck, fix it.
|
||||||
|
$control = new PhabricatorDaemonManagementListWorkflow();
|
||||||
$daemons = $control->loadRunningDaemons();
|
$daemons = $control->loadRunningDaemons();
|
||||||
foreach ($daemons as $daemon) {
|
foreach ($daemons as $daemon) {
|
||||||
if ($daemon->isRunning() &&
|
if ($daemon->isRunning() &&
|
||||||
|
|
Loading…
Reference in a new issue