Reworked the DaemonCommand.
* Accepts options for PID and log file. * Uses posix_kill whenever available. * Checks that the daemon actually started or stopped. * Try to terminate then kill the daemon. * Uses the logger or output instead of "echo".
This commit is contained in:
parent
8bf1d09afd
commit
b87dac145d
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
|
@ -13,21 +14,33 @@ use Monolog\Logger;
|
|||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Daemon that loops and call the run-command.
|
||||
* @author Gabriel Baker <gabriel.baker@autonomicpilot.co.uk>
|
||||
* @package PHPCI
|
||||
* @subpackage Console
|
||||
*/
|
||||
* Daemon that loops and call the run-command.
|
||||
* @author Gabriel Baker <gabriel.baker@autonomicpilot.co.uk>
|
||||
* @package PHPCI
|
||||
* @subpackage Console
|
||||
*/
|
||||
class DaemonCommand extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \Monolog\Logger
|
||||
* @var Logger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $pidFilePath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $logFilePath;
|
||||
|
||||
public function __construct(Logger $logger, $name = null)
|
||||
{
|
||||
parent::__construct($name);
|
||||
|
@ -40,17 +53,30 @@ class DaemonCommand extends Command
|
|||
->setName('phpci:daemon')
|
||||
->setDescription('Initiates the daemon to run commands.')
|
||||
->addArgument(
|
||||
'state',
|
||||
InputArgument::REQUIRED,
|
||||
'start|stop|status'
|
||||
);
|
||||
'state', InputArgument::REQUIRED, 'start|stop|status'
|
||||
)
|
||||
->addOption(
|
||||
'pid-file', 'p', InputOption::VALUE_REQUIRED,
|
||||
'Path of the PID file',
|
||||
implode(DIRECTORY_SEPARATOR,
|
||||
array(PHPCI_DIR, 'daemon', 'daemon.pid'))
|
||||
)
|
||||
->addOption(
|
||||
'log-file', 'l', InputOption::VALUE_REQUIRED,
|
||||
'Path of the log file',
|
||||
implode(DIRECTORY_SEPARATOR,
|
||||
array(PHPCI_DIR, 'daemon', 'daemon.log'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops through running.
|
||||
*/
|
||||
* Loops through running.
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->pidFilePath = $input->getOption('pid-file');
|
||||
$this->logFilePath = $input->getOption('log-file');
|
||||
|
||||
$state = $input->getArgument('state');
|
||||
|
||||
switch ($state) {
|
||||
|
@ -61,64 +87,139 @@ class DaemonCommand extends Command
|
|||
$this->stopDaemon();
|
||||
break;
|
||||
case 'status':
|
||||
$this->statusDaemon();
|
||||
$this->statusDaemon($output);
|
||||
break;
|
||||
default:
|
||||
echo "Not a valid choice, please use start stop or status";
|
||||
$this->output->writeln("<error>Not a valid choice, please use start, stop or status</error>");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function startDaemon()
|
||||
{
|
||||
|
||||
if (file_exists(PHPCI_DIR.'/daemon/daemon.pid')) {
|
||||
echo "Already started\n";
|
||||
$this->logger->warning("Daemon already started");
|
||||
$pid = $this->getRunningPid();
|
||||
if ($pid) {
|
||||
$this->logger->notice("Daemon already started", array('pid' => $pid));
|
||||
return "alreadystarted";
|
||||
}
|
||||
|
||||
$logfile = PHPCI_DIR."/daemon/daemon.log";
|
||||
$this->logger->info("Trying to start the daemon");
|
||||
|
||||
$cmd = "nohup %s/daemonise phpci:daemonise > %s 2>&1 &";
|
||||
$command = sprintf($cmd, PHPCI_DIR, $logfile);
|
||||
$this->logger->info("Daemon started");
|
||||
exec($command);
|
||||
$command = sprintf($cmd, PHPCI_DIR, $this->logFilePath);
|
||||
exec($command, $output, $exitCode);
|
||||
|
||||
if ($exitCode !== 0) {
|
||||
$this->logger->error(sprintf("daemonise exited with status %d",
|
||||
$exitCode));
|
||||
return "notstarted";
|
||||
}
|
||||
|
||||
for ($i = 0; !($pid = $this->getRunningPid()) && $i < 5; $i++) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
if (!$pid) {
|
||||
$this->logger->error("Could not start the daemon");
|
||||
return "notstarted";
|
||||
}
|
||||
|
||||
$this->logger->notice("Daemon started", array('pid' => $pid));
|
||||
return "started";
|
||||
}
|
||||
|
||||
protected function stopDaemon()
|
||||
{
|
||||
|
||||
if (!file_exists(PHPCI_DIR.'/daemon/daemon.pid')) {
|
||||
echo "Not started\n";
|
||||
$this->logger->warning("Can't stop daemon as not started");
|
||||
$pid = $this->getRunningPid();
|
||||
if (!$pid) {
|
||||
$this->logger->notice("Cannot stop the daemon as it is not started");
|
||||
return "notstarted";
|
||||
}
|
||||
|
||||
$cmd = "kill $(cat %s/daemon/daemon.pid)";
|
||||
$command = sprintf($cmd, PHPCI_DIR);
|
||||
exec($command);
|
||||
$this->logger->info("Daemon stopped");
|
||||
unlink(PHPCI_DIR.'/daemon/daemon.pid');
|
||||
}
|
||||
$this->logger->info("Trying to terminate the daemon", array('pid' => $pid));
|
||||
$this->kill($pid, 15);
|
||||
|
||||
protected function statusDaemon()
|
||||
{
|
||||
|
||||
if (!file_exists(PHPCI_DIR.'/daemon/daemon.pid')) {
|
||||
echo "Not running\n";
|
||||
return "notrunning";
|
||||
for ($i = 0; ($pid = $this->getRunningPid()) && $i < 5; $i++) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
$pid = trim(file_get_contents(PHPCI_DIR.'/daemon/daemon.pid'));
|
||||
$pidcheck = sprintf("/proc/%s", $pid);
|
||||
if (is_dir($pidcheck)) {
|
||||
echo "Running\n";
|
||||
if ($pid) {
|
||||
$this->logger->warning("The daemon is resiting, trying to kill it", array('pid' => $pid));
|
||||
$this->kill($pid, 9);
|
||||
|
||||
for ($i = 0; ($pid = $this->getRunningPid()) && $i < 5; $i++) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$pid) {
|
||||
$this->logger->notice("Daemon stopped");
|
||||
return "stopped";
|
||||
}
|
||||
|
||||
$this->logger->error("Could not stop the daemon");
|
||||
}
|
||||
|
||||
protected function statusDaemon(OutputInterface $output)
|
||||
{
|
||||
$pid = $this->getRunningPid();
|
||||
if ($pid) {
|
||||
$output->writeln(sprintf('The daemon is running, PID: %d', $pid));
|
||||
return "running";
|
||||
}
|
||||
|
||||
unlink(PHPCI_DIR.'/daemon/daemon.pid');
|
||||
echo "Not running\n";
|
||||
$output->writeln('The daemon is not running');
|
||||
return "notrunning";
|
||||
}
|
||||
|
||||
/** Check if there is a running daemon
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
protected function getRunningPid()
|
||||
{
|
||||
if (!file_exists($this->pidFilePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pid = intval(trim(file_get_contents($this->pidFilePath)));
|
||||
|
||||
if (function_exists('posix_kill')) {
|
||||
// Use posix_kill with signal 0
|
||||
if (@posix_kill($pid, 0)) {
|
||||
// Signal 0 isn't sent but posix_kill checks the process anyway
|
||||
return $pid;
|
||||
}
|
||||
} elseif (is_dir('/proc')) {
|
||||
// Use linux's /proc filesystem
|
||||
if (is_dir('/proc/' . $pid)) {
|
||||
return $pid;
|
||||
}
|
||||
} else {
|
||||
// Last resort: the ps command
|
||||
exec(sprintf('ps %d', $pid), $output, $exitCode);
|
||||
if ($exitCode === 0) {
|
||||
return $pid;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found, remove the stale PID file
|
||||
unlink($this->pidFilePath);
|
||||
}
|
||||
|
||||
/** Kill a process
|
||||
*
|
||||
* @param int $pid
|
||||
* @param int $signal
|
||||
*/
|
||||
protected function kill($pid, $signal = 15)
|
||||
{
|
||||
if (function_exists('posix_kill')) {
|
||||
return posix_kill($pid, $signal);
|
||||
}
|
||||
|
||||
exec(sprintf('kill -%d %d', $signal, $pid), null, $exitCode);
|
||||
return $exitCode === 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue