diff --git a/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php b/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php --- a/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php +++ b/src/applications/daemon/management/PhabricatorDaemonManagementStatusWorkflow.php @@ -3,6 +3,8 @@ final class PhabricatorDaemonManagementStatusWorkflow extends PhabricatorDaemonManagementWorkflow { + const DEAD_NAME_PREFIX = ' '; + public function didConstruct() { $this ->setName('status') @@ -21,30 +23,53 @@ return 1; } - $status = 0; - printf( - "%-5s\t%-24s\t%s\n", - "PID", - "Started", - "Daemon"); + $status = 0; + $maxName = 0; + $customArgsPresented = false; + foreach ($daemons as $daemon) { $name = $daemon->getName(); if (!$daemon->isRunning()) { - $daemon->updateStatus(PhabricatorDaemonLog::STATUS_DEAD); + $daemon + ->updateStatus(PhabricatorDaemonLog::STATUS_DEAD) + ->markAsDead(); + $status = 2; - $name = ' '.$name; + $name = self::DEAD_NAME_PREFIX . $name; + } + + if (strlen($name) > $maxName) { + $maxName = strlen($name); + } + + if ($daemon->getCustomArgs()) { + $customArgsPresented = true; } + } + + $format = " %-5s\t%-24s\t%-{$maxName}s"; + + if ($customArgsPresented) { + $format .= "\t%s\n"; + } else { + $format .= "\n"; + } + + printf($format, "PID", "Started", "Daemon", "Custom Args"); + + foreach ($daemons as $daemon) { printf( - "%5s\t%-24s\t%s\n", + $format, $daemon->getPID(), $daemon->getEpochStarted() ? date('M j Y, g:i:s A', $daemon->getEpochStarted()) : null, - $name); + $daemon->isDead() + ? self::DEAD_NAME_PREFIX . $daemon->getName() + : $daemon->getName(), + $daemon->getCustomArgs()); } return $status; } - - } diff --git a/src/infrastructure/daemon/control/PhabricatorDaemonReference.php b/src/infrastructure/daemon/control/PhabricatorDaemonReference.php --- a/src/infrastructure/daemon/control/PhabricatorDaemonReference.php +++ b/src/infrastructure/daemon/control/PhabricatorDaemonReference.php @@ -2,11 +2,15 @@ final class PhabricatorDaemonReference { + const UNKNOWN_CUSTOM_ARGS = ''; + private $name; private $pid; private $start; private $pidFile; + private $customArgs; + private $isDead; private $daemonLog; public static function newFromDictionary(array $dict) { @@ -16,18 +20,15 @@ $ref->pid = idx($dict, 'pid'); $ref->start = idx($dict, 'start'); + $ref->customArgs = self::UNKNOWN_CUSTOM_ARGS; + $ref->isDead = false; + return $ref; } public function updateStatus($new_status) { try { - if (!$this->daemonLog) { - $this->daemonLog = id(new PhabricatorDaemonLog())->loadOneWhere( - 'daemon = %s AND pid = %d AND dateCreated = %d', - $this->name, - $this->pid, - $this->start); - } + $this->loadDaemonLog(); if ($this->daemonLog) { $this->daemonLog @@ -43,9 +44,42 @@ // column, as it does not exist yet. // - Daemons running on machines which do not have access to MySQL // (like an IRC bot) will not be able to load or save the log. - // - // } + + return $this; + } + + public function getCustomArgs() { + if ($this->customArgs != self::UNKNOWN_CUSTOM_ARGS) { + return $this->customArgs; + } + + try { + $this->loadDaemonLog(); + + if ($this->daemonLog) { + $argv = $this->daemonLog->getArgv(); + $custom = array(); + + foreach ($argv as $id => $arg) { + // Ignore daemon name + if ($id == 0) { + continue; + } + + if ($this->isArgCustom($arg)) { + $custom[] = $arg; + } + } + + $this->customArgs = implode(' ', $custom); + } + } catch (AphrontQueryException $ex) { + // Ignore anything that goes wrong here. + // See explanations above. + } + + return $this->customArgs; } public function getPID() { @@ -69,6 +103,15 @@ return $this->pidFile; } + public function markAsDead() { + $this->isDead = true; + return $this; + } + + public function isDead() { + return $this->isDead; + } + public function isRunning() { return self::isProcessRunning($this->getPID()); } @@ -109,4 +152,47 @@ return !$this->isRunning(); } + private function loadDaemonLog() { + try { + if (!$this->daemonLog) { + $this->daemonLog = id(new PhabricatorDaemonLog())->loadOneWhere( + 'daemon = %s AND pid = %d AND dateCreated = %d', + $this->name, + $this->pid, + $this->start); + } + } catch (AphrontQueryException $ex) { + // Ignore anything that goes wrong here. + // See explanations above. + } + } + + private function isArgCustom($arg) { + $non_custom_assigns = array( + '--load-phutil-library=', + '--log=', + '--phd=', + ); + + $non_custom_args = array( + '--daemonize', + '--trace', + '--debug', + '--verbose', + ); + + foreach ($non_custom_assigns as $non_custom_assign) { + if (!strncmp($arg, $non_custom_assign, strlen($non_custom_assign))) { + return false; + } + } + + foreach ($non_custom_args as $non_custom_arg) { + if ($arg == $non_custom_arg) { + return false; + } + } + + return true; + } }