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". Added a ProcessControl interface and implementations. Closed #908
This commit is contained in:
parent
15b6917f68
commit
4edefee761
11 changed files with 572 additions and 45 deletions
63
PHPCI/ProcessControl/Factory.php
Normal file
63
PHPCI/ProcessControl/Factory.php
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* Construct an appropriate ProcessControl instance.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
class Factory
|
||||
{
|
||||
/**
|
||||
* ProcessControl singleton.
|
||||
*
|
||||
* @var ProcessControlInterface
|
||||
*/
|
||||
protected static $instance = null;
|
||||
|
||||
/**
|
||||
* Returns the ProcessControl singleton.
|
||||
*
|
||||
* @return ProcessControlInterface
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (static::$instance === null) {
|
||||
static::$instance = static::createProcessControl();
|
||||
}
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ProcessControl depending on available extensions and the underlying OS.
|
||||
*
|
||||
* Check PosixProcessControl, WindowsProcessControl and UnixProcessControl, in that order.
|
||||
*
|
||||
* @return ProcessControlInterface
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function createProcessControl()
|
||||
{
|
||||
switch(true) {
|
||||
case PosixProcessControl::isAvailable():
|
||||
return new PosixProcessControl();
|
||||
|
||||
case WindowsProcessControl::isAvailable():
|
||||
return new WindowsProcessControl();
|
||||
|
||||
case UnixProcessControl::isAvailable():
|
||||
return new UnixProcessControl();
|
||||
}
|
||||
|
||||
throw new \Exception("No ProcessControl implementation available.");
|
||||
}
|
||||
}
|
||||
52
PHPCI/ProcessControl/PosixProcessControl.php
Normal file
52
PHPCI/ProcessControl/PosixProcessControl.php
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* Control process using the POSIX extension.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
class PosixProcessControl implements ProcessControlInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param int $pid
|
||||
* @return bool
|
||||
*/
|
||||
public function isRunning($pid)
|
||||
{
|
||||
// Signal "0" is not sent to the process, but posix_kill checks the process anyway;
|
||||
return posix_kill($pid, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a TERMINATE or KILL signal to the process using posix_kill.
|
||||
*
|
||||
* @param int $pid
|
||||
* @param bool $forcefully Whetehr to send TERMINATE (false) or KILL (true).
|
||||
*/
|
||||
public function kill($pid, $forcefully = false)
|
||||
{
|
||||
posix_kill($pid, $forcefully ? 9 : 15);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this posix_kill is available.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function isAvailable()
|
||||
{
|
||||
return function_exists('posix_kill');
|
||||
}
|
||||
}
|
||||
33
PHPCI/ProcessControl/ProcessControlInterface.php
Normal file
33
PHPCI/ProcessControl/ProcessControlInterface.php
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* A stateless service to check and kill system processes.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
interface ProcessControlInterface
|
||||
{
|
||||
/** Checks if a process exists.
|
||||
*
|
||||
* @param int $pid The process identifier.
|
||||
*
|
||||
* @return boolean true is the process is running, else false.
|
||||
*/
|
||||
public function isRunning($pid);
|
||||
|
||||
/** Terminate a running process.
|
||||
*
|
||||
* @param int $pid The process identifier.
|
||||
* @param bool $forcefully Whether to gently (false) or forcefully (true) terminate the process.
|
||||
*/
|
||||
public function kill($pid, $forcefully = false);
|
||||
}
|
||||
54
PHPCI/ProcessControl/UnixProcessControl.php
Normal file
54
PHPCI/ProcessControl/UnixProcessControl.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* Control processes using the "ps" and "kill" commands.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
class UnixProcessControl implements ProcessControlInterface
|
||||
{
|
||||
/**
|
||||
* Check process using the "ps" command.
|
||||
*
|
||||
* @param int $pid
|
||||
* @return boolean
|
||||
*/
|
||||
public function isRunning($pid)
|
||||
{
|
||||
$output = $exitCode = null;
|
||||
exec(sprintf("ps %d", $pid), $output, $exitCode);
|
||||
return $exitCode === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a signal using the "kill" command.
|
||||
*
|
||||
* @param int $pid
|
||||
* @param bool $forcefully
|
||||
*/
|
||||
public function kill($pid, $forcefully = false)
|
||||
{
|
||||
exec(sprintf("kill -%d %d", $forcefully ? 9 : 15, $pid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the commands "ps" and "kill" are available.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function isAvailable()
|
||||
{
|
||||
return DIRECTORY_SEPARATOR === '/' && exec("which ps") && exec("which kill");
|
||||
}
|
||||
}
|
||||
54
PHPCI/ProcessControl/WindowsProcessControl.php
Normal file
54
PHPCI/ProcessControl/WindowsProcessControl.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
* PHPCI - Continuous Integration for PHP
|
||||
*
|
||||
* @copyright Copyright 2015, Block 8 Limited.
|
||||
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
|
||||
* @link https://www.phptesting.org/
|
||||
*/
|
||||
|
||||
namespace PHPCI\ProcessControl;
|
||||
|
||||
/**
|
||||
* Control processes using the "tasklist" and "taskkill" commands.
|
||||
*
|
||||
* @author Adirelle <adirelle@gmail.com>
|
||||
*/
|
||||
class WindowsProcessControl implements ProcessControlInterface
|
||||
{
|
||||
/**
|
||||
* Check if the process is running using the "tasklist" command.
|
||||
*
|
||||
* @param type $pid
|
||||
* @return bool
|
||||
*/
|
||||
public function isRunning($pid)
|
||||
{
|
||||
$lastLine = exec(sprintf('tasklist /fi "PID eq %d" /nh /fo csv 2>nul:', $pid));
|
||||
$record = str_getcsv($lastLine);
|
||||
return isset($record[1]) && intval($record[1]) === $pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the process using the "taskkill" command.
|
||||
*
|
||||
* @param type $pid
|
||||
* @param bool $forcefully
|
||||
*/
|
||||
public function kill($pid, $forcefully = false)
|
||||
{
|
||||
exec(sprintf("taskkill /t /pid %d %s 2>nul:", $pid, $forcefully ? '/f' : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the commands "tasklist" and "taskkill" are available.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function isAvailable()
|
||||
{
|
||||
return DIRECTORY_SEPARATOR === '\\' && exec("where tasklist") && exec("where taskkill");
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue