++ed by:

1 PAUSE user
4 non-PAUSE users.

Author image Petya Kohts
and 1 contributors


snaked - cron as it should be. Or shouldn't? Please vote!


  # import old cron jobs (TO BE IMPLEMENTED)
  snaked --import-crontabs

  # generate sample configuration (discussed below) in /etc/snaked
  snaked --sample-config

  # check which jobs are configured
  snaked --show-config

  # run in the foreground (CTRL-C to exit)
  snaked --debug

  # run in the background
  snaked --daemon


snaked is a job scheduler, just like cron, which has several unique features making it much more flexible and useful than any other cron implementation.

It is heavily tested on Linux and FreeBSD but might (and hopefully with your help will) be run on any Perl + POSIX compliant system.

limit job execution time

You can choose to configure the maximum limit of time for each job to finish. If job doesn't finish in time it is killed. The limit is independently configurable for each job. Forget about lockf, ps -ef | grep -v grep and cron jobs being run twice and more times concurrently.

You can also configure the upper limit of execution time of any job of the given snaked instance. This global limit is checked independently of the individual job execution time limits.

unique job id and job dependencies

Each snaked job has its unique job identifier which is used to configure job dependencies: for any job you can specify other jobs (addressed by their identifiers) which shouldn't be run with this job concurrently.

So if job A is being executed and time comes to start job B which is configured as conflicting with job A, then the start of job B is postponed until job A is finished.

more often than once a minute

snaked allows jobs to be run more often than once a minute.

Actually snaked supports two execution schedule formats: old cron format with not less than a minute time resolution and snaked job schedule format which specifies how often the jobs is run in seconds, making it possible to run job even once a second!

run from any user, root is not required

Although configuration example below shows snaked run from root, this is not a requirement. snaked doesn't require any specific super-user privileges. Just specify configuration path (with --cfg parameter) accessible by snaked (that's why default log path for example points to /tmp) and run it from any user.


snaked configuration is a directory which contains global instance options (each option in separate file) and associated job definitions where job definition is also a directory with each job option stored in a separate file:

  |-- admin_email
  |-- jobs
  |   |-- every_hour
  |   |   |-- cmd
  |   |   `-- execution_schedule
  |   |-- every_ten_seconds
  |   |   |-- cmd
  |   |   `-- execution_interval
  |   `-- fast_job
  |       |-- cmd
  |       |-- conflicts
  |       `-- execution_interval
  `-- log

Above shown configuration (run "snaked --sample-config" from root to get it) defines admin_email for the snaked instance (optional, defaults to root) and log file path (optional, defaults to /tmp/snaked.log):

  testing18:/etc/snaked# cat admin_email
  testing18:/etc/snaked# cat log

There are three jobs named every_hour, every_ten_seconds and fast_job which append the result of 'uptime' command to /tmp/snaked_every_hour, /tmp/snaked_ten_seconds and /tmp/snaked_fast_job. This is done by running 'cmd' file which resides in job directory -- shell script in sample configuration, this can be any executable allowed by underlying operating system:

  testing18:/etc/snaked/jobs/every_hour# ls -l cmd
  -rwxr-xr-x 1 root root 0 2010-07-07 00:24 cmd
  testing18:/etc/snaked/jobs/every_hour# file cmd
  cmd: POSIX shell script text executable

First job, every_hour, has a parameter execution_schedule which is an old cron schedule example (parsed by Schedule::Cron::Events):

  testing18:/etc/snaked/jobs/every_hour# cat execution_schedule
  0 * * * *

Two other jobs use snaked execution_interval schedule, specifying that every_ten_seconds job should be run once in ten seconds, and fast_job should be run once in every second.

  testing18:/etc/snaked/jobs/every_ten_seconds# cat execution_interval
  testing18:/etc/snaked/jobs/fast_job# cat execution_interval

To make it a bit more explanatory we've defined conflicts option for fast_job which specifies that fast_job should not be run if every_ten_seconds is running:

  testing18:/etc/snaked/jobs/fast_job# cat conflicts

Which translates to "try to run 'fast_job' as often as once a second, but wait if 'every_ten_seconds' job is running".



Optional. Where to send emails about failing jobs. Defaults to root.


Optional. Name of the log filename which holds all the log messages including informational and error messages. Defaults to /tmp/snaked.log.


Optional. Name of the log filename used only for error messages. Defaults to nothing, turning off separate error logging.


Optional. Size of the log file after which it is rotated. Defaults to 10 MB.


Optional. Number of rotated log files to preserve. Defaults to 2.


Optional. Specifies maximum exeuction time limit for all the jobs. Defaults to 2 hours.


Optional. Filename of the pidfile where snaked stores the pid of its main process. Defaults to nothing, which does not generate any pidfile.


Optional. Directory which is used to write detailed status and debugging information (if configured).

Defaults to /tmp/snaked.spool__etc_snaked



Optional. Where to send emails about failures of this job. Defaults to global admin_email option (and overrides it).


Mandatory. Executable with correct file permissions (executable bit on) which is allowed by underlying operating system. Can be shell script or binary.


Optional. Existing file specifies that this job should not be run (see also --enable-jobs and --disable-jobs command line parameters)

execution_interval, execution_schedule

Only one parameter, execution_interval or execution_schedule, is allowed and is mandatory for one job. execution_interval specifies number of seconds (positive integer) between invocations of cmd. execution_schedule specifies standard cron format schedule (first five fields) for the job.


Optional. Specifies time limit for the job, in seconds. Defaults to nothing, turning time limit off.


Optional. Specifies time in seconds between TERM and KILL signals sent to the job when snaked needs to stop the job (when snaked stop or restarts, when job runs too long). Defaults to 60 seconds.


Optional. Time period in seconds. Job failure emails are not sent more often than this time period. First email is sent after first time period of constant failures. This option is used to suppress emails about accidental job failures. Defaults to 0, which turns the feature off (delivers email on every job failure).


Optional. Time period in seconds which specifoes random first run shift in time for the job. Defaults to 0, which turns the feature off.


Optional. Space/line separated list of job identifiers which should wait while this job is running. If any job from this list is currently being executed then the job owning the option will not be executed. Defaults to nothing, allowing the job to be run independently of the status of any other job.

snaked organizes conflicting jobs into job groups, running every job from the job group one by one (if the time for the job has come). This guarantees that every conflicting job is run from time to time though its start time might be shifted because of waiting for the conflicting jobs.


--daemon or --debug [--cfg PATH]

Two main (and mutually exclusive) command-line parameters are --daemon (run in background) and --debug (run in foreground).

--cfg option specifies snaked configuration which is to be used for this snaked copy (defaults to /etc/snaked)

You can run several independent daemons with different configurations.

--stop [--cfg PATH] [--wait]

Request snaked to be stopped. With --wait option this request will not return until snaked is actually stopped.

--configure [--cfg PATH]

Request snaked to reread configuration.

--restart [--cfg PATH]

Request snaked to restart. With --wait option this request will not return until snaked is actually restarted.

--status [--cfg PATH]

Check whether snaked runs.

This is done by traversing all the running processes and finding those which name matches snaked --cfg PATH. If --cfg parameter is not specified then PATH defaults to /etc/snaked

--detailed-status [--cfg PATH]

Dumps detailed state information into spool_directory.


Show snaked version.

--show-config [--cfg PATH]

Dumps the configuration.

--enable-jobs <JOB_LIST> [--cfg PATH]

For every job in JOB_LIST (space separated) remove special 'disabled' file from job directory and request snaked to reread configuration.

--disable-jobs <JOB_LIST> [--cfg PATH]

For every job in JOB_LIST (space separated) add special 'disabled' file tojob directory and request snaked to reread configuration.

--add-job <JOB_NAME> --execution_interval N --cmd BASH_TEXT [--cfg PATH]

Add job named JOB_NAME to the snaked configuration pointed to by PATH (defaults to /etc/snaked). execution_interval is set to N, cmd is set to BASH_TEXT (protect shell special characters with quotes).

Other job parameters can be specified as well.

--delete-jobs <JOB_LIST> [--cfg PATH]

Delete jobs from snaked configuration pointed to by PATH (defaults to /etc/snaked). This command does actually removes whole job directory, consider using --disable-jobs <JOB_LIST> as it is safer.

--modify-job <JOB_NAME> <--parameter> <value> [--cfg PATH]

Replace current value of parameter of the specified job with new value in the snaked configuration pointed to by PATH (defaults to /etc/snaked)

--sample-config [PATH]

Populate PATH or /etc/snaked (must not exist) with sample configuration


Thanks to the whole Yandex team and personally to the following people (in alphabetic order):

  Denis Barov
  Maxim Dementyev
  Eugene Fedotov
  Andrey Grunau
  Andrey Ignatov
  Oleg Leksunin
  Dmitry Parfenov
  Alexey Simakov
  Dmitrij Tejblum
  Julie S Ukhlicheva
  Anton Ustyugov
  Andrey Zonov

for their bug reports, suggestions and contributions.


Petya Kohts <petya@kohts.com>


Copyright 2009 - 2013 Petya Kohts.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.