新贵的 "service start" 可以在 cron 作业中使用吗?

Can upstart's "service start" be used inside a cron job?

TLDR; Is it possible to create a cron job that runs service service_name start? How?

我的内容

sudo crontab -e

是:

45 23 * * * service bormarise_celery_daemon start

这在终端上以 root 或服务器正常运行:

service bormarise_celery_daemon start
start: Job is already running: bormarise_celery_daemon

但 cron 却给出了以下错误:

bormarise_celery_daemon: unrecognized service

tl;博士

您需要将 /sbin 添加到 cron 的 PATH 以便 service 脚本可以找到 initctl。为此,将如下定义添加到 crontab 的顶部:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

如果您尝试开始的工作已经 运行,您可能仍然 运行 遇到 cron 给您发送电子邮件的问题,因为 initctl 以状态 1(失败)退出宁。你可以用类似的东西来解决这个问题:

45 23 * * * service bormarise_celery_daemon status | grep -q running || service bormarise_celery_daemon start

尽管有点长,如果 bormarise_celery_daemon 服务未 运行ning,它应该只尝试 运行 启动命令。

服务与 initctl

虽然 service 命令试图管理 Upstart 作业,但它并不是真正的 Upstart 控制功能——那将是 initctl 和相关的简写命令套件(startstop)。所有 Upstart 脚本都位于 /sbin/.

service 命令试图帮助人们在 Upstart 和经典 SysV 风格的脚本之间传播服务。这样您就可以使用一个界面(service 脚本)来管理来自两个系统的服务。

深入研究服务脚本

如果您在 Ubuntu 14.04 上浏览 service 脚本(它只是一个 Bash 脚本)的实际源代码,您将看到:

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

开仓条件:

  1. 检查您指定的服务(在您的情况下:bormarise_celery_daemon)是否是 Upstart 工作。 Upstart 工作进入 /etc/init/,扩展名为 .conf
  2. 如果是,service 脚本将检查它是否可以 运行 initctl
  3. 如果可以,service 脚本将确保 initctl 是一个足够新的版本。

如果所有这些都是真的,那么 service 脚本将尝试使用适当的 initctl 命令来 运行 Upstart 作业。例如:

service bormarise_celery_daemon start

转换为:

start bormarise_celery_daemon

这(基本上)等同于:

initctl start bormarise_celery_daemon

但是,如果这些条件中的任何一个不成立,service 脚本假定您正在尝试 运行 SysV 风格的脚本。这些只是位于 /etc/init.d/ 中的 Bash 个脚本。但是,如果不存在这样的脚本,它将退出并显示 unrecognized service 错误消息。

拼凑

cron 的默认 PATH 仅包含 /bin//usr/bin/。这意味着它不包括 /sbin/,而 initctl 可执行文件所在的位置。 这意味着 cron 将无法 运行 initctl

cron 运行 是你的 crontab 时,service 脚本 能够找到你的 Upstart 工作,但它是 not 无法 运行 initctl 命令,因此它会跳过尝试通过 Upstart 运行 您的服务(, initctl).相反,它会尝试在 /etc/init.d/ 中寻找 SysV 风格的脚本。由于该脚本不存在,service 脚本放弃并打印您的错误消息。

如果您用 /sbin/ 覆盖 cron 的默认值 PATH,那么 service 脚本将能够找到 initctl 并将尝试启动您的 Upstart 工作。


有趣的是,在 Ubuntu 12.04 上,service 脚本仅检查 Upstart 作业是否存在,而忽略了两项 initctl 检查。这意味着如果您在 Ubuntu 12.04 上尝试此操作,它将尝试使用 Upstart 来启动您的服务。但是,如果 /sbin/ 不在路径上,它将失败并显示(稍微)更易理解的错误消息:

/usr/bin/service: 123: exec: start: not found