tl;dr
You need to add /sbin
to cron's PATH
so the service
script can find initctl
. To do that, add a definition like this to the top of your crontab:
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
You may still run into issues with cron
emailing you since initctl
exits with status 1 (fail) if the job you try to start is already running. You could get around that with something like:
45 23 * * * service bormarise_celery_daemon status | grep -q running || service bormarise_celery_daemon start
Despite being a bit long, it should only try to run the start command if the bormarise_celery_daemon
service isn't running.
service vs initctl
While the service
command makes an attempt to manage Upstart jobs, it is not the actual Upstart control function -- that would be initctl
and the related suite of short-hand commands (i.e., start
, stop
, etc.). All of the Upstart scripts reside in /sbin/
.
The service
command tries to facilitate people spreading services between both Upstart and classic SysV-style scripts. That way you can use one interface (the service
script) to manage services from both systems.
Delving into the service Script
If you browse the actual source of the service
script (it's just a Bash script) on Ubuntu 14.04, you'll see:
if [ -r "/etc/init/${SERVICE}.conf" ] && which initctl >/dev/null \
&& initctl version | grep -q upstart
then
# Upstart configuration exists for this job and we're running on upstart
case "${ACTION}" in
start|stop|status|reload)
# Action is a valid upstart action
exec ${ACTION} ${SERVICE} ${OPTIONS}
;;
restart)
# Map restart to the usual sysvinit behavior.
stop ${SERVICE} ${OPTIONS} || :
exec start ${SERVICE} ${OPTIONS}
;;
force-reload)
# Upstart just uses reload for force-reload
exec reload ${SERVICE} ${OPTIONS}
;;
esac
fi
The opening conditional:
- Checks if the service you specified (in your case:
bormarise_celery_daemon
) is an Upstart job. Upstart jobs go into /etc/init/
with a .conf
extension.
- If it is, the
service
script will check to see if it can run initctl
.
- If it can, the
service
script will then make sure that initctl
is a new-enough version.
If all of that is true, then the service
script will try to use the appropriate initctl
command to run the Upstart job. For example:
service bormarise_celery_daemon start
translates into:
start bormarise_celery_daemon
which is (basically) equivalent to:
initctl start bormarise_celery_daemon
However, if any of those conditions is not true, the service
script assumes you're trying to run a SysV-style script. These are just Bash scripts located in /etc/init.d/
. However, if no such script exists, it will exit with the unrecognized service
error message.
Putting the Pieces Together
The default PATH
for cron only contains /bin/
and /usr/bin/
. This means it doesn't include /sbin/
which is where the initctl
executable is. This means cron
will not be able to run initctl
.
When cron
runs your crontab, the service
script is able to find your Upstart job, but it is not able to run the initctl
command, so it skips over trying to run your service via Upstart (i.e., initctl
). Instead, it then tries to look for a SysV-style script in /etc/init.d/
. Since that script doesn't exist, the service
script gives up and prints your error message.
If you override cron
's default PATH
with one including /sbin/
, then the service
script will be able to find initctl
and will attempt to launch your Upstart job.
Interestingly, on Ubuntu 12.04 the service
script only checks to see if an Upstart job exists, omitting both initctl
checks. That means if you were trying this on Ubuntu 12.04, it would attempt to use Upstart to start your service. However, if /sbin/
isn't on the path, it would fail with a (slightly) more intelligible error message:
/usr/bin/service: 123: exec: start: not found