Differential D11855 Diff 28615 src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/daemon/management/PhabricatorDaemonManagementWorkflow.php
| Show First 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | if ($debug) { | ||||
| } else { | } else { | ||||
| $console->writeOut( | $console->writeOut( | ||||
| pht( | pht( | ||||
| "Launching daemon \"%s\".\n", | "Launching daemon \"%s\".\n", | ||||
| $daemon)); | $daemon)); | ||||
| } | } | ||||
| } | } | ||||
| foreach ($argv as $key => $arg) { | |||||
| $argv[$key] = escapeshellarg($arg); | |||||
| } | |||||
| $flags = array(); | $flags = array(); | ||||
| if ($debug || PhabricatorEnv::getEnvConfig('phd.trace')) { | if ($debug || PhabricatorEnv::getEnvConfig('phd.trace')) { | ||||
| $flags[] = '--trace'; | $flags[] = '--trace'; | ||||
| } | } | ||||
| if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) { | if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) { | ||||
| $flags[] = '--verbose'; | $flags[] = '--verbose'; | ||||
| } | } | ||||
| $config = array(); | |||||
| if (!$debug) { | if (!$debug) { | ||||
| $flags[] = '--daemonize'; | $config['daemonize'] = true; | ||||
| } | } | ||||
| if (!$debug) { | if (!$debug) { | ||||
| $log_file = $this->getLogDirectory().'/daemons.log'; | $config['log'] = $this->getLogDirectory().'/daemons.log'; | ||||
| $flags[] = csprintf('--log=%s', $log_file); | |||||
| } | } | ||||
| $pid_dir = $this->getPIDDirectory(); | $pid_dir = $this->getPIDDirectory(); | ||||
| // TODO: This should be a much better user experience. | // TODO: This should be a much better user experience. | ||||
| Filesystem::assertExists($pid_dir); | Filesystem::assertExists($pid_dir); | ||||
| Filesystem::assertIsDirectory($pid_dir); | Filesystem::assertIsDirectory($pid_dir); | ||||
| Filesystem::assertWritable($pid_dir); | Filesystem::assertWritable($pid_dir); | ||||
| $flags[] = csprintf('--phd=%s', $pid_dir); | $config['piddir'] = $pid_dir; | ||||
| $command = csprintf( | $config['daemons'] = array( | ||||
| './phd-daemon %s %C %C', | array( | ||||
| $daemon, | 'class' => $daemon, | ||||
| implode(' ', $flags), | 'argv' => $argv, | ||||
| implode(' ', $argv)); | ), | ||||
| ); | |||||
| $command = csprintf('./phd-daemon %Ls', $flags); | |||||
| $phabricator_root = dirname(phutil_get_library_root('phabricator')); | $phabricator_root = dirname(phutil_get_library_root('phabricator')); | ||||
| $daemon_script_dir = $phabricator_root.'/scripts/daemon/'; | $daemon_script_dir = $phabricator_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(__CLASS__, 'ignoreSignal')); | array(__CLASS__, 'ignoreSignal')); | ||||
| echo "\n phabricator/scripts/daemon/ \$ {$command}\n\n"; | echo "\n phabricator/scripts/daemon/ \$ {$command}\n\n"; | ||||
| phutil_passthru('(cd %s && exec %C)', $daemon_script_dir, $command); | $tempfile = new TempFile('daemon.config'); | ||||
| Filesystem::writeFile($tempfile, json_encode($config)); | |||||
| phutil_passthru( | |||||
| '(cd %s && exec %C < %s)', | |||||
| $daemon_script_dir, | |||||
| $command, | |||||
| $tempfile); | |||||
| } else { | } else { | ||||
| try { | try { | ||||
| $this->executeDaemonLaunchCommand( | $this->executeDaemonLaunchCommand( | ||||
| $command, | $command, | ||||
| $daemon_script_dir, | $daemon_script_dir, | ||||
| $config, | |||||
| $this->runDaemonsAsUser); | $this->runDaemonsAsUser); | ||||
| } catch (Exception $e) { | } catch (Exception $e) { | ||||
| // Retry without sudo | // Retry without sudo | ||||
| $console->writeOut(pht( | $console->writeOut(pht( | ||||
| "sudo command failed. Starting daemon as current user\n")); | "sudo command failed. Starting daemon as current user\n")); | ||||
| $this->executeDaemonLaunchCommand( | $this->executeDaemonLaunchCommand( | ||||
| $command, | $command, | ||||
| $daemon_script_dir); | $daemon_script_dir, | ||||
| $config); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| private function executeDaemonLaunchCommand( | private function executeDaemonLaunchCommand( | ||||
| $command, | $command, | ||||
| $daemon_script_dir, | $daemon_script_dir, | ||||
| array $config, | |||||
| $run_as_user = null) { | $run_as_user = null) { | ||||
| $is_sudo = false; | $is_sudo = false; | ||||
| if ($run_as_user) { | if ($run_as_user) { | ||||
| // If anything else besides sudo should be | // If anything else besides sudo should be | ||||
| // supported then insert it here (runuser, su, ...) | // supported then insert it here (runuser, su, ...) | ||||
| $command = csprintf( | $command = csprintf( | ||||
| 'sudo -En -u %s -- %C', | 'sudo -En -u %s -- %C', | ||||
| $run_as_user, | $run_as_user, | ||||
| $command); | $command); | ||||
| $is_sudo = true; | $is_sudo = true; | ||||
| } | } | ||||
| $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($daemon_script_dir); | $future->setCWD($daemon_script_dir); | ||||
| $future->write(json_encode($config)); | |||||
| list($stdout, $stderr) = $future->resolvex(); | list($stdout, $stderr) = $future->resolvex(); | ||||
| if ($is_sudo) { | if ($is_sudo) { | ||||
| // On OSX, `sudo -n` exits 0 when the user does not have permission to | // On OSX, `sudo -n` exits 0 when the user does not have permission to | ||||
| // switch accounts without a password. This is not consistent with | // switch accounts without a password. This is not consistent with | ||||
| // sudo on Linux, and seems buggy/broken. Check for this by string | // sudo on Linux, and seems buggy/broken. Check for this by string | ||||
| // matching the output. | // matching the output. | ||||
| if (preg_match('/sudo: a password is required/', $stderr)) { | if (preg_match('/sudo: a password is required/', $stderr)) { | ||||
| ▲ Show 20 Lines • Show All 306 Lines • Show Last 20 Lines | |||||