【问题标题】:Why is my docker container not executing my cron job?为什么我的 docker 容器没有执行我的 cron 作业?
【发布时间】:2023-03-21 22:51:01
【问题描述】:

我有一个想要定期运行的node 脚本,因此我创建了以下Dockerfile 来从cron 任务运行它:

FROM node:8

RUN apt-get update && apt-get install -y cron

# ensure the node packages are installed in the image
WORKDIR /usr/src/app
COPY package.json . 
RUN npm install

# copy the node task to working directory
COPY db-update.js .

# copy the script which will start cron to the working directory
COPY startcron.sh .

# copy the cron task to the cond.d directory
COPY crontask /etc/cron.d/crontask

# give execution rights on the cron job and script
RUN chmod 0644 /etc/cron.d/crontask && chmod 777 ./startcron.sh

# apply the cron job
RUN crontab /etc/cron.d/crontask

# create the log file to be able to run tail
RUN touch /var/log/cron.log

# execute the command in the foreground
CMD /usr/src/app/startcron.sh

startcron.sh bash 脚本中,我有以下内容:

#!/bin/bash
set -e

printenv | sed 's/^\(.*\)$/export \1/g' > /tmp/env.sh

echo 'Starting cron' # <- ONLY THIS APPEARS IN MY CONTAINER LOGS
cron -f

我需要创建/tmp/env.sh 来导出我的node 脚本所需的环境变量。然后,此脚本应在前台启动 cron。我的crontask 应该“获取”这些环境变量并运行我的node 脚本。如果我已经正确设置了所有内容,我希望在我的 Docker 容器的日志中看到我的节点脚本的输出。

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
# │ │ │ │ │                                       7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * *  command to execute
# DOES THIS COMMAND EXECUTE SUCCESSFULLY, IF NOT WHY NOT?
*/5 * * * * . /tmp/env.sh /usr/local/bin/node /usr/src/app/db-update.js > /proc/1/fd/1 2>/proc/1/fd/2
# need to leave an empty line

这是我的节点脚本中的一个 sn-p:

const sftpclient = require('ssh2-sftp-client');
const expressGraphQL = require('express-graphql');
const mongoose = require('mongoose');
const fs = require('fs');

console.log('now executing db-update');
const IN_PRODUCTION = (process.env.NODE_ENV === 'production' ? true : false);
console.log('what is node env: ', process.env.NODE_ENV);
console.log('what is env: ', process.env);

但是,当我运行此容器时,我在容器日志中看到的唯一输出是来自我的 bash 脚本“Starting Cron”的 echo 命令。我没有看到节点脚本的任何输出,但容器继续运行。如何确保node 脚本运行,或者如果没有,容器会失败?

【问题讨论】:

标签: node.js bash docker cron


【解决方案1】:

为了让您的生活更轻松,我建议您更改策略以使用简单的无限循环和睡眠而不是 cron

所以在 CMD 中只需放置 while true; sleep 300; execute-node-program || exit 1; done

在这样的策略中:

  1. 您的节点程序的所有输出都在 docker 日志中
  2. 如果您的程序失败,容器将失败

使用 cron 很难实现这一点,因为您可能需要为 2 个进程放置 systemd:

  1. 一个 cron 进程
  2. 第二个进程观察什么是节点程序输出并在需要时终止 systemd,打印日志等。

编辑:

因此,让您了解如何在 cron 作业失败时杀死您的容器:

  1. 使用--init 标志启动您的容器,例如docker run --init... - 这非常重要,可以让你从容器中杀死主容器的进程
  2. 使用类似的crontab记录:*/5 * * * * bash -c "/tmp/env.sh &amp;&amp; /usr/local/bin/node /usr/src/app/db-update.js || pkill -9 -f cron" &gt; /proc/1/fd/1 2&gt;/proc/1/fd/2

【讨论】:

  • 感谢您的建议!我想我可能已经通过在前台执行 cron (cron -f) 并将输出发送到控制台并使用以下内容解决了这个问题:/usr/src/app/db-update.js &gt; /proc/1/fd/1 2&gt;/proc/1/fd/2。我在网上看到过一些帖子,其他人已经实现了我所做的部分工作。我喜欢你的解决方案,但我觉得使用cron 已经快到了,我真的很想在我放弃之前弄清楚我哪里出错了。
  • 谢谢。如果我按照您的指定修改我的 crontask,我将如何获取必要的环境变量并运行节点脚本?
  • 我根据你的情况进行了调整:)
  • 非常感谢!它抱怨权限被拒绝,但至少我可以看到 cron 正在运行并以我可以检测到的错误停止容器。感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-23
  • 2013-06-10
  • 1970-01-01
  • 1970-01-01
  • 2023-01-22
  • 1970-01-01
  • 2017-03-03
相关资源
最近更新 更多