Fix schedule/cron implementation

This commit is contained in:
Dennis Eichhorn 2018-08-04 13:20:57 +02:00
parent a33a7be954
commit d7337e9e1b
12 changed files with 197 additions and 82 deletions

View File

@ -30,9 +30,10 @@ class Cron extends SchedulerAbstract
*/ */
public function create(TaskAbstract $task) : void public function create(TaskAbstract $task) : void
{ {
$this->run('-l > tmpcron'); $this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
\file_put_contents('tmpcron', "\n" . $task->__toString(), FILE_APPEND); \file_put_contents(__DIR__ . '/tmpcron.tmp', $task->__toString() . "\n", FILE_APPEND);
$this->run('tmpcron'); $this->run(__DIR__ . '/tmpcron.tmp');
unlink(__DIR__ . '/tmpcron.tmp');
} }
/** /**
@ -40,16 +41,16 @@ class Cron extends SchedulerAbstract
*/ */
public function update(TaskAbstract $task) : void public function update(TaskAbstract $task) : void
{ {
$this->run('-l > tmpcron'); $this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
$new = ''; $new = '';
$fp = \fopen('tmpcron', 'r+'); $fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+');
if ($fp) { if ($fp) {
$line = \fgets($fp); $line = \fgets($fp);
while ($line !== false) { while ($line !== false) {
if ($line[0] !== '#' && \stripos($line, '/tn = ' . $task->getId()) !== false) { if ($line[0] !== '#' && \stripos($line, 'name="' . $task->getId()) !== false) {
$new .= $task->__toString(); $new .= $task->__toString() . "\n";
} else { } else {
$new .= $line . "\n"; $new .= $line . "\n";
} }
@ -57,11 +58,12 @@ class Cron extends SchedulerAbstract
$line = \fgets($fp); $line = \fgets($fp);
} }
\fwrite($fp, $new);
\fclose($fp); \fclose($fp);
\file_put_contents(__DIR__ . '/tmpcron.tmp', $new);
} }
$this->run('tmpcron'); $this->run(__DIR__ . '/tmpcron.tmp');
unlink(__DIR__ . '/tmpcron.tmp');
} }
/** /**
@ -69,15 +71,23 @@ class Cron extends SchedulerAbstract
*/ */
public function delete(TaskAbstract $task) : void public function delete(TaskAbstract $task) : void
{ {
$this->run('-l > tmpcron'); $this->deleteByName($task->getId());
}
/**
* {@inheritdoc}
*/
public function deleteByName(string $name) : void
{
$this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
$new = ''; $new = '';
$fp = \fopen('tmpcron', 'r+'); $fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+');
if ($fp) { if ($fp) {
$line = \fgets($fp); $line = \fgets($fp);
while ($line !== false) { while ($line !== false) {
if ($line[0] !== '#' && \stripos($line, '/tn = ' . $task->getId()) !== false) { if ($line[0] !== '#' && \stripos($line, 'name="' . $name) !== false) {
$line = \fgets($fp); $line = \fgets($fp);
continue; continue;
} }
@ -86,11 +96,12 @@ class Cron extends SchedulerAbstract
$line = \fgets($fp); $line = \fgets($fp);
} }
\fwrite($fp, $new);
\fclose($fp); \fclose($fp);
\file_put_contents(__DIR__ . '/tmpcron.tmp', $new);
} }
$this->run('tmpcron'); $this->run(__DIR__ . '/tmpcron.tmp');
unlink(__DIR__ . '/tmpcron.tmp');
} }
/** /**
@ -98,16 +109,31 @@ class Cron extends SchedulerAbstract
*/ */
public function getAll() : array public function getAll() : array
{ {
$lines = \explode("\n", $this->normalize($this->run('-l'))); $this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
unset($lines[0]);
$jobs = []; $jobs = [];
foreach ($lines as $line) { $fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+');
if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false) {
$jobs[] = CronJob::createWith(\str_getcsv($line, ' ')); if ($fp) {
$line = \fgets($fp);
while ($line !== false) {
if ($line[0] !== '#') {
$elements = [];
$namePos = \stripos($line, 'name="');
$elements[] = \substr($line, $namePos + 6, \stripos($line, '"', $namePos + 7) - 1);
$elements += \explode(' ', $line);
$jobs[] = CronJob::createWith($elements);
}
$line = \fgets($fp);
} }
\fclose($fp);
} }
$this->run(__DIR__ . '/tmpcron.tmp');
unlink(__DIR__ . '/tmpcron.tmp');
return $jobs; return $jobs;
} }
@ -116,29 +142,30 @@ class Cron extends SchedulerAbstract
*/ */
public function getAllByName(string $name, bool $exact = true) : array public function getAllByName(string $name, bool $exact = true) : array
{ {
$lines = \explode("\n", $this->normalize($this->run('-l'))); $this->run('-l > ' . __DIR__ . '/tmpcron.tmp');
unset($lines[0]);
if ($exact) { $jobs = [];
$jobs = []; $fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+');
foreach ($lines as $line) {
$csv = \str_getcsv($line, ' ');
if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false && $csv[5] === $name) { if ($fp) {
$jobs[] = CronJob::createWith($csv); $line = \fgets($fp);
while ($line !== false) {
if ($line[0] !== '#' && \stripos($line, '# name="' . $name) !== false) {
$elements = [];
$elements[] = $name;
$elements += \explode(' ', $line);
$jobs[] = CronJob::createWith($elements);
} }
}
} else {
$jobs = [];
foreach ($lines as $line) {
$csv = \str_getcsv($line, ' ');
if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false && \stripos($csv[5], $name) !== false) { $line = \fgets($fp);
$jobs[] = CronJob::createWith($csv);
}
} }
\fclose($fp);
} }
$this->run(__DIR__ . '/tmpcron.tmp');
unlink(__DIR__ . '/tmpcron.tmp');
return $jobs; return $jobs;
} }
} }

View File

@ -31,7 +31,7 @@ class CronJob extends TaskAbstract
*/ */
public function __toString() : string public function __toString() : string
{ {
return ''; return $this->interval . ' ' . $this->command . ' # name="' . $this->id . '" ' . $this->comment;
} }
/** /**
@ -39,7 +39,8 @@ class CronJob extends TaskAbstract
*/ */
public static function createWith(array $jobData) : TaskAbstract public static function createWith(array $jobData) : TaskAbstract
{ {
$job = new self($jobData[1], ''); $interval = \array_splice($jobData, 1, 4);
$job = new self($jobData[0], $jobData[1], \implode(' ', $interval));
return $job; return $job;
} }

View File

@ -0,0 +1,27 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package TBD
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace phpOMS\Utils\TaskSchedule;
/**
* CronJob class.
*
* @package Framework
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
class NullCronJob extends CronJob
{
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Orange Management
*
* PHP Version 7.2
*
* @package TBD
* @copyright Dennis Eichhorn
* @license OMS License 1.0
* @version 1.0.0
* @link http://website.orange-management.de
*/
declare(strict_types=1);
namespace phpOMS\Utils\TaskSchedule;
/**
* CronJob class.
*
* @package Framework
* @license OMS License 1.0
* @link http://website.orange-management.de
* @since 1.0.0
*/
class NullSchedule extends Schedule
{
}

View File

@ -39,9 +39,8 @@ class Schedule extends TaskAbstract
*/ */
public static function createWith(array $jobData) : TaskAbstract public static function createWith(array $jobData) : TaskAbstract
{ {
$job = new self($jobData[1], ''); $job = new self($jobData[1], $jobData[8]);
$job->setRun($jobData[8]);
$job->setStatus($jobData[3]); $job->setStatus($jobData[3]);
if (DateTime::isValid($jobData[2])) { if (DateTime::isValid($jobData[2])) {

View File

@ -83,6 +83,8 @@ abstract class SchedulerAbstract
'e:/WINDOWS/system32/schtasks.exe', 'e:/WINDOWS/system32/schtasks.exe',
'f:/WINDOWS/system32/schtasks.exe', 'f:/WINDOWS/system32/schtasks.exe',
'/usr/bin/crontab', '/usr/bin/crontab',
'/usr/local/bin/crontab',
'/usr/local/sbin/crontab',
'/usr/sbin/crontab', '/usr/sbin/crontab',
'/bin/crontab', '/bin/crontab',
'/sbin/crontab', '/sbin/crontab',
@ -190,6 +192,17 @@ abstract class SchedulerAbstract
*/ */
abstract public function update(TaskAbstract $task) : void; abstract public function update(TaskAbstract $task) : void;
/**
* Delete task by name
*
* @param string $name Task name
*
* @return void
*
* @since 1.0.0
*/
abstract public function deleteByName(string $name) : void;
/** /**
* Delete task * Delete task
* *

View File

@ -41,12 +41,12 @@ abstract class TaskAbstract
protected $command = ''; protected $command = '';
/** /**
* Command/script to run. * Run interval
* *
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $run = ''; protected $interval = '';
/** /**
* Status of the task * Status of the task
@ -91,10 +91,11 @@ abstract class TaskAbstract
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function __construct(string $name, string $cmd = '') public function __construct(string $name, string $cmd = '', string $interval = '')
{ {
$this->id = $name; $this->id = $name;
$this->command = $cmd; $this->command = $cmd;
$this->interval = $interval;
$this->lastRunTime = new \DateTime('1900-01-01'); $this->lastRunTime = new \DateTime('1900-01-01');
$this->nextRunTime = new \DateTime('1900-01-01'); $this->nextRunTime = new \DateTime('1900-01-01');
} }
@ -147,29 +148,29 @@ abstract class TaskAbstract
} }
/** /**
* Get command/script to run * Get interval to create the task
* *
* @return string * @return string
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function getRun() : string public function getInterval() : string
{ {
return $this->run; return $this->interval;
} }
/** /**
* Set script to run * Set interval to create the task
* *
* @param string $run Command/script to run * @param string $interval Interval
* *
* @return void * @return void
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function setRun(string $run) : void public function setInterval(string $interval) : void
{ {
$this->run = $run; $this->interval = $interval;
} }
/** /**

View File

@ -41,12 +41,20 @@ class TaskScheduler extends SchedulerAbstract
$this->run('/Change ' . $task->__toString()); $this->run('/Change ' . $task->__toString());
} }
/**
* {@inheritdoc}
*/
public function deleteByName(string $name) : void
{
$this->run('/Delete /TN ' . $name);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function delete(TaskAbstract $task) : void public function delete(TaskAbstract $task) : void
{ {
$this->run('/Delete /TN ' . $task->getId()); $this->deleteByName($task->getId());
} }
/** /**

View File

@ -26,24 +26,29 @@ class CronTest extends \PHPUnit\Framework\TestCase
public function testCRUD() public function testCRUD()
{ {
if (\stristr(PHP_OS, 'LINUX')) { if (\stristr(PHP_OS, 'LINUX')) {
Cron::guessBin();
$cron = new Cron(); $cron = new Cron();
self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); self::assertEquals([], $cron->getAllByName('testCronJob', false));
$cron->create( $job = new CronJob('testCronJob', 'testFile', '0 0 1 1 *');
new CronJob('testCronJob', 'testFile') $cron->create($job);
);
self::assertEquals('testFile', $cron->getRun());
$cron->update( self::assertTrue(!empty($cron->getAllByName('testCronJob', false)));
new CronJob('testCronJob', 'testFile2') if (!empty($cron->getAllByName('testCronJob', false))) {
); self::assertEquals('testFile', $cron->getAllByName('testCronJob', false)[0]->getCommand());
self::assertEquals('testFile2', $cron->getRun()); }
$cron->delete( $job->setCommand('testFile2');
new CronJob('testCronJob', 'testFile2') $cron->update($job);
);
self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); self::assertTrue(!empty($cron->getAllByName('testCronJob', false)));
if (!empty($cron->getAllByName('testCronJob', false))) {
self::assertEquals('testFile2', $cron->getAllByName('testCronJob', false)[0]->getCommand());
}
$cron->delete($job);
self::assertEquals([], $cron->getAllByName('testCronJob', false));
} }
} }
} }

View File

@ -19,6 +19,6 @@ class SchedulerAbstractTest extends \PHPUnit\Framework\TestCase
{ {
public function testDefault() public function testDefault()
{ {
self::assertEquals('', SchedulerAbstract::getBin()); self::assertTrue(SchedulerAbstract::getBin() === '' || \file_exists(SchedulerAbstract::getBin() ));
} }
} }

View File

@ -22,6 +22,11 @@ class TaskAbstractTest extends \PHPUnit\Framework\TestCase
protected function setUp() protected function setUp()
{ {
$this->class = new class('') extends TaskAbstract { $this->class = new class('') extends TaskAbstract {
public function __toString() : string
{
return '';
}
public static function createWith(array $jobData) : TaskAbstract public static function createWith(array $jobData) : TaskAbstract
{ {
@ -33,7 +38,6 @@ class TaskAbstractTest extends \PHPUnit\Framework\TestCase
{ {
self::assertEquals('', $this->class->getId()); self::assertEquals('', $this->class->getId());
self::assertEquals('', $this->class->getCommand()); self::assertEquals('', $this->class->getCommand());
self::assertEquals('', $this->class->getRun());
self::assertEquals('', $this->class->getStatus()); self::assertEquals('', $this->class->getStatus());
self::assertInstanceOf('\DateTime', $this->class->getNextRunTime()); self::assertInstanceOf('\DateTime', $this->class->getNextRunTime());
self::assertInstanceOf('\DateTime', $this->class->getLastRuntime()); self::assertInstanceOf('\DateTime', $this->class->getLastRuntime());
@ -45,9 +49,6 @@ class TaskAbstractTest extends \PHPUnit\Framework\TestCase
$this->class->setCommand('Command'); $this->class->setCommand('Command');
self::assertEquals('Command', $this->class->getCommand()); self::assertEquals('Command', $this->class->getCommand());
$this->class->setRun('Run');
self::assertEquals('Run', $this->class->getRun());
$this->class->setStatus('Status'); $this->class->setStatus('Status');
self::assertEquals('Status', $this->class->getStatus()); self::assertEquals('Status', $this->class->getStatus());

View File

@ -14,6 +14,7 @@
namespace phpOMS\tests\Utils\TaskSchedule; namespace phpOMS\tests\Utils\TaskSchedule;
use phpOMS\Utils\TaskSchedule\TaskScheduler; use phpOMS\Utils\TaskSchedule\TaskScheduler;
use phpOMS\Utils\TaskSchedule\Schedule;
class TaskSchedulerTest extends \PHPUnit\Framework\TestCase class TaskSchedulerTest extends \PHPUnit\Framework\TestCase
{ {
@ -25,24 +26,29 @@ class TaskSchedulerTest extends \PHPUnit\Framework\TestCase
public function testCRUD() public function testCRUD()
{ {
if (\stristr(PHP_OS, 'WIN')) { if (\stristr(PHP_OS, 'WIN')) {
$cron = new Cron(); TaskScheduler::guessBin();
$cron = new TaskScheduler();
self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); self::assertEquals([], $cron->getAllByName('testCronJob', false));
$cron->create( $job = new Schedule('testCronJob', 'testFile', '0 0 1 1 *');
new CronJob('testCronJob', 'testFile') $cron->create($job);
);
self::assertEquals('testFile', $cron->getRun());
$cron->update( self::assertTrue(!empty($cron->getAllByName('testCronJob', false)));
new CronJob('testCronJob', 'testFile2') if (!empty($cron->getAllByName('testCronJob', false))) {
); self::assertEquals('testFile', $cron->getAllByName('testCronJob', false)[0]->getCommand());
self::assertEquals('testFile2', $cron->getRun()); }
$cron->delete( $job->setCommand('testFile2');
new CronJob('testCronJob', 'testFile2') $cron->update($job);
);
self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); self::assertTrue(!empty($cron->getAllByName('testCronJob', false)));
if (!empty($cron->getAllByName('testCronJob', false))) {
self::assertEquals('testFile2', $cron->getAllByName('testCronJob', false)[0]->getCommand());
}
$cron->delete($job);
self::assertEquals([], $cron->getAllByName('testCronJob', false));
} }
} }
} }