/** * Raise more useful errors when there are basic filesystem problems. */ private function assertLocalExists() { if (!$this->usesLocalWorkingCopy()) { return; } $local = $this->getLocalPath(); Filesystem::assertExists($local); Filesystem::assertIsDirectory($local); Filesystem::assertReadable($local); }
protected final function launchDaemons(array $daemons, $debug, $run_as_current_user = false) { // Convert any shorthand classnames like "taskmaster" into proper class // names. foreach ($daemons as $key => $daemon) { $class = $this->findDaemonClass($daemon['class']); $daemons[$key]['class'] = $class; } $console = PhutilConsole::getConsole(); if (!$run_as_current_user) { // Check if the script is started as the correct user $phd_user = PhabricatorEnv::getEnvConfig('phd.user'); $current_user = posix_getpwuid(posix_geteuid()); $current_user = $current_user['name']; if ($phd_user && $phd_user != $current_user) { if ($debug) { throw new PhutilArgumentUsageException(pht("You are trying to run a daemon as a nonstandard user, " . "and `%s` was not able to `%s` to the correct user. \n" . 'Phabricator is configured to run daemons as "%s", ' . 'but the current user is "%s". ' . "\n" . 'Use `%s` to run as a different user, pass `%s` to ignore this ' . 'warning, or edit `%s` to change the configuration.', 'phd', 'sudo', $phd_user, $current_user, 'sudo', '--as-current-user', 'phd.user')); } else { $this->runDaemonsAsUser = $phd_user; $console->writeOut(pht('Starting daemons as %s', $phd_user) . "\n"); } } } $this->printLaunchingDaemons($daemons, $debug); $flags = array(); if ($debug || PhabricatorEnv::getEnvConfig('phd.trace')) { $flags[] = '--trace'; } if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) { $flags[] = '--verbose'; } $instance = PhabricatorEnv::getEnvConfig('cluster.instance'); if ($instance) { $flags[] = '-l'; $flags[] = $instance; } $config = array(); if (!$debug) { $config['daemonize'] = true; } if (!$debug) { $config['log'] = $this->getLogDirectory() . '/daemons.log'; } $pid_dir = $this->getPIDDirectory(); // TODO: This should be a much better user experience. Filesystem::assertExists($pid_dir); Filesystem::assertIsDirectory($pid_dir); Filesystem::assertWritable($pid_dir); $config['piddir'] = $pid_dir; $config['daemons'] = $daemons; $command = csprintf('./phd-daemon %Ls', $flags); $phabricator_root = dirname(phutil_get_library_root('phabricator')); $daemon_script_dir = $phabricator_root . '/scripts/daemon/'; if ($debug) { // Don't terminate when the user sends ^C; it will be sent to the // subprocess which will terminate normally. pcntl_signal(SIGINT, array(__CLASS__, 'ignoreSignal')); echo "\n phabricator/scripts/daemon/ \$ {$command}\n\n"; $tempfile = new TempFile('daemon.config'); Filesystem::writeFile($tempfile, json_encode($config)); phutil_passthru('(cd %s && exec %C < %s)', $daemon_script_dir, $command, $tempfile); } else { try { $this->executeDaemonLaunchCommand($command, $daemon_script_dir, $config, $this->runDaemonsAsUser); } catch (Exception $e) { // Retry without sudo $console->writeOut("%s\n", pht('sudo command failed. Starting daemon as current user.')); $this->executeDaemonLaunchCommand($command, $daemon_script_dir, $config); } } }
protected final function launchDaemon($class, array $argv, $debug) { $daemon = $this->findDaemonClass($class); $console = PhutilConsole::getConsole(); if ($debug) { if ($argv) { $console->writeOut(pht("Launching daemon \"%s\" in debug mode (not daemonized) " . "with arguments %s.\n", $daemon, csprintf('%LR', $argv))); } else { $console->writeOut(pht("Launching daemon \"%s\" in debug mode (not daemonized).\n", $daemon)); } } else { if ($argv) { $console->writeOut(pht("Launching daemon \"%s\" with arguments %s.\n", $daemon, csprintf('%LR', $argv))); } else { $console->writeOut(pht("Launching daemon \"%s\".\n", $daemon)); } } foreach ($argv as $key => $arg) { $argv[$key] = escapeshellarg($arg); } $flags = array(); if ($debug || PhabricatorEnv::getEnvConfig('phd.trace')) { $flags[] = '--trace'; } if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) { $flags[] = '--verbose'; } if (!$debug) { $flags[] = '--daemonize'; } if (!$debug) { $log_file = $this->getLogDirectory() . '/daemons.log'; $flags[] = csprintf('--log=%s', $log_file); } $pid_dir = $this->getPIDDirectory(); // TODO: This should be a much better user experience. Filesystem::assertExists($pid_dir); Filesystem::assertIsDirectory($pid_dir); Filesystem::assertWritable($pid_dir); $flags[] = csprintf('--phd=%s', $pid_dir); $command = csprintf('./phd-daemon %s %C %C', $daemon, implode(' ', $flags), implode(' ', $argv)); $phabricator_root = dirname(phutil_get_library_root('phabricator')); $daemon_script_dir = $phabricator_root . '/scripts/daemon/'; if ($debug) { // Don't terminate when the user sends ^C; it will be sent to the // subprocess which will terminate normally. pcntl_signal(SIGINT, array(__CLASS__, 'ignoreSignal')); echo "\n phabricator/scripts/daemon/ \$ {$command}\n\n"; phutil_passthru('(cd %s && exec %C)', $daemon_script_dir, $command); } else { $future = new ExecFuture('exec %C', $command); // Play games to keep 'ps' looking reasonable. $future->setCWD($daemon_script_dir); $future->resolvex(); } }
public function launchDaemon($daemon, array $argv, $debug = false) { $symbols = $this->loadAvailableDaemonClasses(); $symbols = ipull($symbols, 'name', 'name'); if (empty($symbols[$daemon])) { throw new Exception("Daemon '{$daemon}' is not loaded, misspelled or abstract."); } $libphutil_root = dirname(phutil_get_library_root('phutil')); $launch_daemon = $libphutil_root . '/scripts/daemon/'; foreach ($argv as $key => $arg) { $argv[$key] = escapeshellarg($arg); } $flags = array(); if ($debug || PhabricatorEnv::getEnvConfig('phd.trace')) { $flags[] = '--trace'; } if ($debug || PhabricatorEnv::getEnvConfig('phd.verbose')) { $flags[] = '--verbose'; } if (!$debug) { $flags[] = '--daemonize'; } $bootloader = PhutilBootloader::getInstance(); foreach ($bootloader->getAllLibraries() as $library) { if ($library == 'phutil') { // No need to load libphutil, it's necessarily loaded implicitly by the // daemon itself. continue; } $flags[] = csprintf('--load-phutil-library=%s', phutil_get_library_root($library)); } $flags[] = csprintf('--conduit-uri=%s', PhabricatorEnv::getURI('/api/')); if (!$debug) { $log_file = $this->getLogDirectory() . '/daemons.log'; $flags[] = csprintf('--log=%s', $log_file); } $pid_dir = $this->getPIDDirectory(); // TODO: This should be a much better user experience. Filesystem::assertExists($pid_dir); Filesystem::assertIsDirectory($pid_dir); Filesystem::assertWritable($pid_dir); $flags[] = csprintf('--phd=%s', $pid_dir); $command = csprintf('./launch_daemon.php %s %C %C', $daemon, implode(' ', $flags), implode(' ', $argv)); if ($debug) { // Don't terminate when the user sends ^C; it will be sent to the // subprocess which will terminate normally. pcntl_signal(SIGINT, array('PhabricatorDaemonControl', 'ignoreSignal')); echo "\n libphutil/scripts/daemon/ \$ {$command}\n\n"; phutil_passthru('(cd %s && exec %C)', $launch_daemon, $command); } else { $future = new ExecFuture('exec %C', $command); // Play games to keep 'ps' looking reasonable. $future->setCWD($launch_daemon); $future->resolvex(); } }
public function launchDaemon($daemon, array $argv, $debug = false) { $symbols = $this->loadAvailableDaemonClasses(); $symbols = ipull($symbols, 'name', 'name'); if (empty($symbols[$daemon])) { throw new Exception("Daemon '{$daemon}' is not known."); } $pid_dir = $this->getControlDirectory('pid'); $log_dir = $this->getControlDirectory('log') . '/daemons.log'; $libphutil_root = dirname(phutil_get_library_root('phutil')); $launch_daemon = $libphutil_root . '/scripts/daemon/'; // TODO: This should be a much better user experience. Filesystem::assertExists($pid_dir); Filesystem::assertIsDirectory($pid_dir); Filesystem::assertWritable($pid_dir); foreach ($argv as $key => $arg) { $argv[$key] = escapeshellarg($arg); } $bootloader = PhutilBootloader::getInstance(); $all_libraries = $bootloader->getAllLibraries(); $non_default_libraries = array_diff($all_libraries, array('phutil', 'phabricator')); $extra_libraries = array(); foreach ($non_default_libraries as $library) { $extra_libraries[] = csprintf('--load-phutil-library=%s', phutil_get_library_root($library)); } $command = csprintf("./launch_daemon.php " . "%s " . "--load-phutil-library=%s " . "%C " . "--conduit-uri=%s " . "--phd=%s " . ($debug ? '--trace ' : '--daemonize '), $daemon, phutil_get_library_root('phabricator'), implode(' ', $extra_libraries), PhabricatorEnv::getURI('/api/'), $pid_dir); if (!$debug) { // If we're running "phd debug", send output straight to the console // instead of to a logfile. $command = csprintf("%C --log=%s", $command, $log_dir); } // Append the daemon's argv. $command = csprintf("%C %C", $command, implode(' ', $argv)); if ($debug) { // Don't terminate when the user sends ^C; it will be sent to the // subprocess which will terminate normally. pcntl_signal(SIGINT, array('PhabricatorDaemonControl', 'ignoreSignal')); echo "\n libphutil/scripts/daemon/ \$ {$command}\n\n"; phutil_passthru('(cd %s && exec %C)', $launch_daemon, $command); } else { $future = new ExecFuture('exec %C', $command); // Play games to keep 'ps' looking reasonable. $future->setCWD($launch_daemon); $future->resolvex(); } }