Docker cron 计划作业未 运行

Docker cron scheduled job not running

我正在尝试使用基于 Alpine 图像的 docker 容器来 运行 计划的 cron 作业,遵循此 tutorial,但是在我的启动脚本中打印语句之后,容器刚刚退出,没有 运行ning 我的其他脚本。

我的docker-compose服务配置如下:

  cron:
    image: alpine:3.11
    command: /usr/local/startup.sh && crond -f -l 8
    volumes:
      - ./cron_tasks_folder/1min:/etc/periodic/1min/:ro
      - ./cron_tasks_folder/15min:/etc/periodic/15min/:ro
      - ./cron_tasks_folder/hourly:/etc/periodic/hourly/:ro
      - ./scripts/startup.sh:/usr/local/startup.sh:ro

所以它 运行 是一个名为 startup.sh 的初始脚本,然后启动 cron 守护进程。 startup.sh 脚本包含以下内容:

#!/bin/sh

echo "Starting startup.sh.."
echo "*       *       *       *       *       run-parts /etc/periodic/1min" >> /etc/crontabs/root
crontab -l
sleep 300

我在那里放了一个睡眠命令,这样我就可以在容器上启动一个交互式 shell 并确保它里面的一切看起来都很好。该脚本为 1 分钟脚本创建了另一个文件夹。我在那里添加了一个测试脚本,我可以验证它在那里:

/etc/periodic/1min # ls -a
.           ..          testScript

脚本可执行:

/etc/periodic/1min # ls -l testScript 
-rwxr-xr-x    1 root     root            31 Jul 30 01:51 testScript

testScript 只是一个 echo 语句,以确保它首先工作:

echo "The donkey is in charge"

并查看 etc/crontabs 中的 root 文件,我看到以下内容(我已经多次重新 运行 容器,每次都创建一个新的 1 分钟文件夹,这是不必要的,但我认为不是这里的问题):

# do daily/weekly/monthly maintenance
# min   hour    day     month   weekday command
*/15    *       *       *       *       run-parts /etc/periodic/15min
0       *       *       *       *       run-parts /etc/periodic/hourly
0       2       *       *       *       run-parts /etc/periodic/daily
0       3       *       *       6       run-parts /etc/periodic/weekly
0       5       1       *       *       run-parts /etc/periodic/monthly

*       *       *       *       *       run-parts /etc/periodic/1min
*       *       *       *       *       run-parts /etc/periodic/1min
*       *       *       *       *       run-parts /etc/periodic/1min
*       *       *       *       *       run-parts /etc/periodic/1min
*       *       *       *       *       run-parts /etc/periodic/1min

testScript 中的 echo 语句从未打印到我的终端,并且容器在启动后不久以退出代码 0 退出。我想每分钟都打印这条声明......我错过了什么?

在 docker 撰写文件中你有

    command: /usr/local/startup.sh && crond -f -l 8

意图是 运行 作为 shell 命令,但从问题中完全不清楚会发生什么;这取决于您的 ENTRYPOINT。由于它是用 [] 括号定义的,因此不会提供额外的 shell。 command 值将作为参数传递给 ENTRYPOINT.

假设变为shell命令,&&在shell 运行的左侧,如果成功,则 运行 位于右侧。所以startup.sh需要在crond执行之前完成startup.sh

结尾
sleep 300

crond 仅在 300 秒后 被调用。

在任何一种情况下,crond 要么根本没有被调用,要么 sleep 还没有完成。注释显示发现了从 crond 开始的错误。

使用这样的入口点是之前配置环境的标准做法,或者在调用主可执行文件时提供 运行时间参数。要正确执行此操作,您应该确保将 exec 用于 运行 主可执行文件,以便它接收信号,否则这些信号将转到 bash shell 运行设置入口点脚本。

所以在 startup.sh 结束时:

exec crond -f -l 8

shell运行宁startup.sh替换为crond,使crond接收所有信号(此时 shell 消失了)。这很微妙但很重要!

一般而言,应使应用程序的调用尽可能简单。例如,您的执行过程分为入口点、命令和启动脚本,它们之间没有明确的接口。如果您将 crond 直接放入 Dockerfile 并将其留在那儿,您就不会挂断调用。有时必须在 运行 时提供参数,但环境变量 - 具有 名称 ,而不仅仅是位置 - 通常是首选。这使调用简单且调试简单。但是,当这不起作用时,shell 脚本入口点是一个很好的解决方案 - 只要确保 exec 你的最终过程!