PHPackages                             deploy-dog/slavedriver - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. deploy-dog/slavedriver

ArchivedLibrary[Queues &amp; Workers](/categories/queues)

deploy-dog/slavedriver
======================

 A PHP based cron job runner. Manage, monitor, log and react to problems with your scheduled tasks.

v1.1.0(5y ago)541.3k1MITPHPPHP ^7.0CI failing

Since May 14Pushed 5y ago1 watchersCompare

[ Source](https://github.com/deploy-dog/slavedriver)[ Packagist](https://packagist.org/packages/deploy-dog/slavedriver)[ Docs](https://github.com/deploy-dog/slavedriver)[ RSS](/packages/deploy-dog-slavedriver/feed)WikiDiscussions master Synced 2mo ago

READMEChangelog (10)Dependencies (7)Versions (15)Used By (0)

Slavedriver
===========

[](#slavedriver)

A PHP based cron job runner. Manage, monitor, log and react to problems with your scheduled tasks. Created by the team at [deploy.dog](https://deploy.dog) initially for internal use, but modified and released for other to enjoy too. Created by [deploy.dog](https://deploy.dog) initially for internal use, but released for others to enjoy too.

[![Travis CI](https://camo.githubusercontent.com/cd310f73e5e9dfc923c644edfa4032b54a1b3904cb4cc604128dbfef72db1a3f/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f6465706c6f792d646f672f736c6176656472697665722e7376673f6d61784167653d33363030)](https://travis-ci.org/deploy-dog/slavedriver)[![Packagist](https://camo.githubusercontent.com/baef2033b827b2e899130830c7fd0230a2bc5b919a00c3521093f3b80c97a7c5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6465706c6f792d646f672f736c6176656472697665722e7376673f6d61784167653d33363030)](https://packagist.org/packages/deploy-dog/slavedriver)[![Packagist](https://camo.githubusercontent.com/654b24784e7e03f313aad904d4a0f370b0a94b8decc51a4320369a3ad8d292d8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6465706c6f792d646f672f736c6176656472697665722e7376673f6d61784167653d33363030)](https://github.com/deploy-dog/slavedriver)[![Packagist](https://camo.githubusercontent.com/d79bc8f17d9060c53908ae60ce5c088676f3a397a64dd91b130c3f50064e83fc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f6465706c6f792d646f672f736c6176656472697665722e7376673f6d61784167653d33363030)](https://github.com/deploy-dog/slavedriver)[![Packagist](https://camo.githubusercontent.com/c915c9ffa1e4b623e1a2cfb6a23c90c5167afbb5daa9184e7170c78e7a485c4e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6465706c6f792d646f672f736c6176656472697665722e7376673f6d61784167653d33363030)](https://github.com/deploy-dog/slavedriver/blob/master/LICENSE.md)[![PHP 7 ready](https://camo.githubusercontent.com/4ff44ef45564fc50c05b7d7976f1e86b62988c82da7af20f695bf610c762333a/687474703a2f2f7068703772656164792e74696d6573706c696e7465722e63682f6465706c6f792d646f672f736c6176656472697665722f6d61737465722f62616467652e737667)](https://travis-ci.org/deploy-dog/slavedriver)

[![deploy.dog - Finally, website deployments done right!](https://camo.githubusercontent.com/6a75e1e833cc5903f0ff9b3c338d84f0f2fe649fc0dcdc7368e66ca773616032/68747470733a2f2f6465706c6f792e646f672f6173736574732f4c6f676f732f456d61696c2e706e67)](https://deploy.dog)

Requirements
------------

[](#requirements)

- PHP 5.6, 7.0, 7.1 or HHVM
- Unix based OS such as Linux, FreeBSD or MacOS *(Windows is not supported at this time)*

Installation (via Composer obviously)
-------------------------------------

[](#installation-via-composer-obviously)

```
composer require deploy-dog/slavedriver
```

Usage
-----

[](#usage)

### Create your file which describes your jobs.

[](#create-your-file-which-describes-your-jobs)

We suggest using a file named `slavedriver.php` in the project root, and that's what we'll be using in this example.

**A more detailed example of this file can be seen [here](https://github.com/deploy-dog/slavedriver/blob/master/slavedriver.php), but the basics are below**

```
// You'll need autoloading
require_once __DIR__ . '/vendor/autoload.php';

// We recommend scrapbook for your PSR-16 compatible cache, but use whatever you like!
// This example is using Scrapbook and Flysystem to write a cache file to the disk, but you'll
// probably want to use Redis or something better like that
$adapter = new \League\Flysystem\Adapter\Local('/tmp/dd.slavedriver.cache', LOCK_EX);
$filesystem = new \League\Flysystem\Filesystem($adapter);
$cache = new \MatthiasMullie\Scrapbook\Adapters\Flysystem($filesystem);
$simpleCache = new \MatthiasMullie\Scrapbook\Psr16\SimpleCache($cache);

// In this example, we use phossa2/event which is a PSR-14 event manager.
// PSR-14 is only "proposed" at this stage. Once PSR-14 is "accepted" we'll update the required interface.
// You can use anything that implments \Phossa2\Event\Interfaces\EventManagerInterface (which is a copy of PSR-14),
// it doesn't actually have to be phossa2/event
$eventsDispatcher = new \Phossa2\Event\EventDispatcher();
$eventsDispatcher->attach(\deploydog\Slavedriver\Slavedriver::EVENT_SLAVEDRIVER_ALL, function(\Phossa2\Event\Event $event) {
    $job = $event->getTarget();
    // See Events in the readme below for details on events
});

// Instantiate Slavedriver
$slavedriver = new \deploydog\Slavedriver\Slavedriver($simpleCache, $eventsDispatcher);

// Want logging (in addition to events)? See the Logging section of the readme below

// You can set the Slave Name that the machine running this job has (so it know which jobs to do).
// We'll look at the following (in this order)
// Manually set using $slavedriver->setSlaveName()
// Environment var "SLAVEDRIVER_SLAVE_NAME"
// Node hostname (from php's gethostname() function)
$slavedriver->setSlaveName('test1');

// Create a job
$job = new \deploydog\Slavedriver\Job('Sleep for a bit');
$job->setCommand('sleep 10');
$job->setTimeout(14);
$job->setWarnIfNotFinishedAfterSeconds(11);
$job->setSchedule('* * * * *');
$job->setSlaves(['test1']); // Optional, default to all slaves

// Add the job to Slavedriver
$slavedriver->addJob($job);

// Add more jobs like with the example above..

// Alternatively (or in addition) if you have lots of jobs you might want to include one per file
// and get Slavedriver to recursively look in directory for jobs
// Your included files should return an instance of the Job object.
$slavedriver->addAllJobsInDirectory(__DIR__.'/DirWithJobs');

// Run the required jobs
$slavedriver->run();
```

### Running Slavedriver

[](#running-slavedriver)

You need to get something (e.g. the real system crontab) to run your Slavedriver file every 1 minute (this time internal is important, don't change it).

```
* * * * * cd /path/to/project && php slavedriver.php 1>> /dev/null 2>&1

```

Events
------

[](#events)

Events are dispatched throughout the process which you can listen to. You can use any [PSR-14 (Event Manager)](https://github.com/php-fig/fig-standards/blob/master/proposed/event-manager.md) compatible event manager. PSR-14 is currently at the "proposed" stage so we should expect it to change. We'd recommend using [phossa2/event](https://github.com/phossa2/event)as your PSR-14 event manager if you don't have one currently and don't want to implement your own. As PSR-14 is not out yet, we require a class which implements Phossa2\\Event\\Interfaces\\EventManagerInterface so if you don't want to use phossa2/event you can write something else which implements that same class. Not ideal, I know, and we expect to change this in v2 when PSR-14 is approved.

You can listen to the follow events to monitor your Slavedriver jobs and act accordingly.

*Hint: Use the Job's `CustomData` if you want to pass through additional data, such as whether to wake people up in the night if the job fails!*

### Catching events

[](#catching-events)

#### Handling specific events

[](#handling-specific-events)

```
$eventsDispatcher = new \Phossa2\Event\EventDispatcher(); // This is the same one you passed into Slavedriver on construct
$eventsDispatcher->attach(\deploydog\Slavedriver\Slavedriver::EVENT_JOB_OUTPUT_STDOUT, function(\Phossa2\Event\Event $event) {
     $job = $event->getTarget();
     $stdOut = $event->getParam('stdOut');

     // Log $stdOut somewhere, this can be called multiple times for each job and will be given any
     // new stdOut since the last call. You can then append this to the previous stdOut of the job
     // Likewise the event "slavedriver.job.output.stderr" will give you the stdErr in $event->getParam('stdErr')
});
```

### Handling all Slavedriver events

[](#handling-all-slavedriver-events)

```
$eventsDispatcher = new \Phossa2\Event\EventDispatcher(); // This is the same one you passed into Slavedriver on construct
$eventsDispatcher->attach(\deploydog\Slavedriver\Slavedriver::EVENT_SLAVEDRIVER_ALL, function(\Phossa2\Event\Event $event) {
    $job = $event->getTarget();

    if ($job instanceof \deploydog\Slavedriver\Job) {
        echo 'Got event "'.$event->getName().'" on job "'.$job->getName().'"'."\n";
    } else {
        echo 'Got event "'.$event->getName().'"'."\n";
    }

    if ($event->getName() == \deploydog\Slavedriver\Slavedriver::EVENT_JOB_OUTPUT_STDOUT){
        echo 'stdOut > ' . $event->getParam('stdOut')."\n";
    } else if ($event->getName() == \deploydog\Slavedriver\Slavedriver::EVENT_JOB_OUTPUT_STDERR){
        echo 'stdErr > ' . $event->getParam('stdErr')."\n";
    }
});
```

### Slavedriver itself started (should be roughly every 1 minute)

[](#slavedriver-itself-started-should-be-roughly-every-1-minute)

- Event: `slavedriver.started`
- Event constant: `Slavedriver::EVENT_SLAVEDRIVER_STARTED`
- Event target: *None*
- Event params: *None*

### Job started

[](#job-started)

- Event: `slavedriver.job.started`
- Event constant: `Slavedriver::EVENT_JOB_STARTED`
- Event target: The `Job` object
- Event params: *None*

### Job finished successfully

[](#job-finished-successfully)

- Event: `slavedriver.job.finished.success`
- Event constant: `Slavedriver::EVENT_JOB_FINISHED_SUCCESS`
- Event target: The `Job` object
- Event params: *None*

### Job finished with error (based on exit code)

[](#job-finished-with-error-based-on-exit-code)

- Event: `slavedriver.job.finished.error`
- Event constant: `Slavedriver::EVENT_JOB_FINISHED_ERROR`
- Event target: The `Job` object
- Event params:
    - `exitCode` = The exit code of the command

### Job stdOut data (this is called every few seconds with additional data)

[](#job-stdout-data-this-is-called-every-few-seconds-with-additional-data)

- Event: `slavedriver.job.output.stdout`
- Event constant: `Slavedriver::EVENT_JOB_OUTPUT_STDOUT`
- Event target: The `Job` object
- Event params:
    - `stdOut` = The stdOut data since the last trigger of this event

### Job stdErr data (this is called every few seconds with additional data)

[](#job-stderr-data-this-is-called-every-few-seconds-with-additional-data)

- Event: `slavedriver.job.output.stderr`
- Event constant: `Slavedriver::EVENT_JOB_OUTPUT_STDERR`
- Event target: The `Job` object
- Event params:
    - `stdErr` = The stdErr data since the last trigger of this event

### Job was still running when the timeout value was hit (and it will have been killed)

[](#job-was-still-running-when-the-timeout-value-was-hit-and-it-will-have-been-killed)

- Event: `slavedriver.job.timeout`
- Event constant: `Slavedriver::EVENT_JOB_TIMEOUT`
- Event target: The `Job` object
- Event params: *None*

### Job should have been started but the last instance was still running and they cannot overlap

[](#job-should-have-been-started-but-the-last-instance-was-still-running--and-they-cannot-overlap)

- Event: `slavedriver.job.last_instance_still_running`
- Event constant: `Slavedriver::EVENT_JOB_LAST_INSTANCE_STILL_RUNNING`
- Event target: The `Job` object
- Event params: *None*

### Job still running but expected runtime has elapsed (job not killed)

[](#job-still-running-but-expected-runtime-has-elapsed-job-not-killed)

- Event: `slavedriver.job.expected_runtime_elapsed`
- Event constant: `Slavedriver::EVENT_JOB_EXPECTED_RUNTIME_ELAPSED`
- Event target: The `Job` object
- Event params: *None*

Logging
-------

[](#logging)

Logging is provided by any [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) compatible logger. You can provider custom log levels for different messages if you wish, or leave the leave the log levels at the defaults which are sensible. To setup logging, call the `setLogger()` method on the Slavedriver object, passing in the PSR-3 logger and optionally the log levels.

```
$logger = new \Monolog\Logger('Slavedriver');
$logger->pushHandler(new \Monolog\Handler\StreamHandler(__DIR__.'/slavedriver.log'));

$slavedriver->setLogger($logger);
```

Or with custom log levels (e.g. override the `ErrorExitCode` log level to `alert`)

```
$logLevels = new \deploydog\Slavedriver\LogLevels();
$logLevels->setErrorExitCode(\Psr\Log\LogLevel::ALERT);

$slavedriver->setLogger($logger, $logLevels);
```

Exceptions
----------

[](#exceptions)

All exceptions thrown by Slavedriver extend the base Slavedriver exception `deploydog\Slavedriver\Exception\Slavedriver` which extends the base PHP exception `\Exception`. Different Slavedriver exceptions are thrown for different reasons, for example `InvalidJob` and `InvalidSlavedriverConfig`. Check the [Exceptions](https://github.com/deploy-dog/slavedriver/tree/master/src/deploydog/Slavedriver/Exception) directory for the possible options.

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity27

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity66

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~111 days

Recently: every ~194 days

Total

14

Last Release

1839d ago

PHP version history (3 changes)v1.0.0PHP ^5.0 || ^7.0

v1.0.2PHP ^5.6 || ^7.0

v1.1.0PHP ^7.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/916b54090a031ca520c8c10859bc1f999387c3f955c36b12f7edd96fb459a8c5?d=identicon)[violuke](/maintainers/violuke)

---

Top Contributors

[![violuke](https://avatars.githubusercontent.com/u/6420347?v=4)](https://github.com/violuke "violuke (58 commits)")

---

Tags

background-jobscroncron-jobscrontabphpscheduled-tasksjobcrontaskjobscrontabcronjobscheduled jobstask-runnerjob-runnerscheduled-taskscronjobsscheduled taskscheduled job

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/deploy-dog-slavedriver/health.svg)

```
[![Health](https://phpackages.com/badges/deploy-dog-slavedriver/health.svg)](https://phpackages.com/packages/deploy-dog-slavedriver)
```

###  Alternatives

[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[orisai/scheduler

Cron job scheduler - with locks, parallelism and more

4037.1k4](/packages/orisai-scheduler)[jms/job-queue-bundle

Allows to run and schedule Symfony console commands as background jobs.

3462.3M5](/packages/jms-job-queue-bundle)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)[aboutcoders/job-bundle

A symfony bundle for asynchronous job processing.

2618.0k1](/packages/aboutcoders-job-bundle)[panlatent/schedule

Schedule plugin for CraftCMS

1034.1k](/packages/panlatent-schedule)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
