diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -363,6 +363,8 @@ 'PhutilPostmarkFuture' => 'future/postmark/PhutilPostmarkFuture.php', 'PhutilPregsprintfTestCase' => 'xsprintf/__tests__/PhutilPregsprintfTestCase.php', 'PhutilProcessGroupDaemon' => 'daemon/torture/PhutilProcessGroupDaemon.php', + 'PhutilProcessQuery' => 'filesystem/PhutilProcessQuery.php', + 'PhutilProcessRef' => 'filesystem/PhutilProcessRef.php', 'PhutilProseDiff' => 'utils/PhutilProseDiff.php', 'PhutilProseDiffTestCase' => 'utils/__tests__/PhutilProseDiffTestCase.php', 'PhutilProseDifferenceEngine' => 'utils/PhutilProseDifferenceEngine.php', @@ -1027,6 +1029,8 @@ 'PhutilPostmarkFuture' => 'FutureProxy', 'PhutilPregsprintfTestCase' => 'PhutilTestCase', 'PhutilProcessGroupDaemon' => 'PhutilTortureTestDaemon', + 'PhutilProcessQuery' => 'Phobject', + 'PhutilProcessRef' => 'Phobject', 'PhutilProseDiff' => 'Phobject', 'PhutilProseDiffTestCase' => 'PhutilTestCase', 'PhutilProseDifferenceEngine' => 'Phobject', diff --git a/src/filesystem/PhutilProcessQuery.php b/src/filesystem/PhutilProcessQuery.php new file mode 100644 --- /dev/null +++ b/src/filesystem/PhutilProcessQuery.php @@ -0,0 +1,83 @@ +isOverseer = $is_overseer; + return $this; + } + + public function withInstances(array $instances) { + $this->instances = $instances; + return $this; + } + + public function execute() { + if (phutil_is_windows()) { + throw new Exception( + pht( + 'Querying system processes is not currently supported on '. + 'Windows.')); + } + + // TODO: See T12827. This formulation likely does not work properly on + // Solaris. + + list($processes) = execx('ps -o pid,command -a -x -w -w -w'); + $processes = phutil_split_lines($processes, false); + + $refs = array(); + foreach ($processes as $process) { + $parts = preg_split('/\s+/', trim($process), 2); + list($pid, $command) = $parts; + + $ref = id(new PhutilProcessRef()) + ->setPID((int)$pid) + ->setCommand($command); + + // If this process is a "phd-daemon" process, mark it as a daemon + // overseer. + $is_overseer = (bool)preg_match('/\bphd-daemon\b/', $command); + $ref->setIsOverseer($is_overseer); + + // If this is an overseer and the command has a "-l" ("Label") argument, + // the argument contains the "PHABRICATOR_INSTANCE" value for the daemon. + // Parse it out and annotate the process. + $instance = null; + if ($ref->getIsOverseer()) { + $matches = null; + if (preg_match('/-l (\S+)/', $command, $matches)) { + $instance = $matches[1]; + } + } + + $ref->setInstance($instance); + + $refs[] = $ref; + } + + if ($this->isOverseer !== null) { + foreach ($refs as $key => $ref) { + if ($ref->getIsOverseer() !== $this->isOverseer) { + unset($refs[$key]); + } + } + } + + if ($this->instances) { + $instances_map = array_fuse($this->instances); + foreach ($refs as $key => $ref) { + if (!isset($instances_map[$ref->getInstance()])) { + unset($refs[$key]); + } + } + } + + return array_values($refs); + } + +} diff --git a/src/filesystem/PhutilProcessRef.php b/src/filesystem/PhutilProcessRef.php new file mode 100644 --- /dev/null +++ b/src/filesystem/PhutilProcessRef.php @@ -0,0 +1,47 @@ +pid = $pid; + return $this; + } + + public function getPID() { + return $this->pid; + } + + public function setCommand($command) { + $this->command = $command; + return $this; + } + + public function getCommand() { + return $this->command; + } + + public function setIsOverseer($is_overseer) { + $this->isOverseer = $is_overseer; + return $this; + } + + public function getIsOverseer() { + return $this->isOverseer; + } + + public function setInstance($instance) { + $this->instance = $instance; + return $this; + } + + public function getInstance() { + return $this->instance; + } + +}