在Docker容器的前台运行cron不会产生任何输出

qxsslcnc  于 2023-02-07  发布在  Docker
关注(0)|答案(2)|浏览(216)

我想在Docker容器中运行一些cron作业,并将输出发送到stdout。How to run a cron job inside a docker container?
为了用一个简单的例子来尝试这个方法,我创建了一个演示crontab:
我的电子表格:

* * * * * date > /dev/stdout 2> /dev/stderr
# empty line

然后,我在Docker容器中运行一个交互式shell,它基于脚本所需的图像:

docker run -it --entrypoint bash python:3.10.3-bullseye

/# apt update
/# apt install cron
/# crontab < my-crontab
/# cron -f

如果我等待60秒,我希望每分钟看到一次连接到容器的控制台的输出,但是没有输出。
最后,我在/var/spool/mail/mail中找到了输出。

From root@5e3c82cb3651 Tue May 10 20:04:02 2022
Return-path: <root@5e3c82cb3651>
Envelope-to: root@5e3c82cb3651
Delivery-date: Tue, 10 May 2022 20:04:02 +0000
Received: from root by 5e3c82cb3651 with local (Exim 4.94.2)
    (envelope-from <root@5e3c82cb3651>)
    id 1noW5S-0000SA-0T
    for root@5e3c82cb3651; Tue, 10 May 2022 20:04:02 +0000
From: root@5e3c82cb3651 (Cron Daemon)
To: root@5e3c82cb3651
Subject: Cron <root@5e3c82cb3651> date > /dev/stdout 2> /dev/stderr
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=root>
Message-Id: <E1noW5S-0000SA-0T@5e3c82cb3651>
Date: Tue, 10 May 2022 20:04:02 +0000

Tue May 10 20:04:01 UTC 2022

然后看起来/bin/sh完全忽略了crontab中的shell重定向。

vd8tlhqk

vd8tlhqk1#

@DavidMaze在他的评论中回答了这个问题(上面-找不到链接)。重定向到/proc/1/fd/1和/proc/1/fd/2(对于stderr)完全有效。谢谢你,David。
然而,这是违反直觉的。文件系统节点/dev/stdout和/dev/stderr已经作为符号链接存在,它们分别指向/proc/1/fd/1和/proc/1/fd/2,独立于cron。为什么cmd > /dev/stdoutcmd > /proc/1/fd/1不能在crontab中互换呢?

j9per5c4

j9per5c42#

cron是很久以前写的。可以预料到,它对docker并不友好。它希望任务不产生输出。如果它们产生输出,则认为是错误,cron尝试通过电子邮件向负责人报告。有一些技巧可以使cron任务的输出在docker logs中可见。但是为什么不选择docker友好的cron实现呢?
其中之一是supercronic
docker-compose.yml

services:
  supercronic:
    build: .
    command: supercronic crontab

Dockerfile

FROM alpine:3.17
RUN set -x \
    && apk add --no-cache supercronic shadow \
    && useradd -m app
USER app
COPY crontab .

crontab

* * * * * date

一个gist,包含更多信息。
另一个不错的例子是yacron,但是它使用了YAML。
ofelia也可以使用,但是它们似乎专注于在单独的容器中运行任务,这可能不是缺点,但是我不确定我为什么要这样做。
但是如果你坚持传统的,你可以在我的other answer中找到一对。

相关问题