我想在Docker容器中运行一些CRON作业,然后将输出发送到STDOUT。我读了这篇文章:一个docker容器?
为了用一个简单的示例尝试一下,我创建了一个演示crontab:
my-crontab:
* * * * * date > /dev/stdout 2> /dev/stderr
# empty line
然后,我根据脚本需要的图像在docker容器中运行一个交互式外壳,
docker run -it --entrypoint bash python:3.10.3-bullseye
/# apt update
/# apt install cron
/# crontab < my-crontab
/# cron -f
如果我等待60几秒钟,我希望每分钟每分钟一次连接到容器上的控制台。但是没有输出。
最后,我在/var/spool/邮件/邮件中找到了输出。这是一条消息:
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中的外壳重定向。
I want to run some cron jobs in a Docker container and send the output to stdout. I read this post: How to run a cron job inside a docker container?
To try this out with a simple example, I created a demo crontab:
my-crontab:
* * * * * date > /dev/stdout 2> /dev/stderr
# empty line
Then I run an interactive shell inside a Docker container based on the image my scripts will need:
docker run -it --entrypoint bash python:3.10.3-bullseye
/# apt update
/# apt install cron
/# crontab < my-crontab
/# cron -f
If I wait 60 seconds, I expect to see some output to the console attached to the container once every minute. But there is no output.
Finally, I found the output in /var/spool/mail/mail. Here is one message:
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
Then it looks like /bin/sh is completely ignoring the shell redirection in the crontab.
发布评论
评论(3)
@DavidMaze在他的评论中回答了这一点(上面 - 找不到指向它的链接)。重定向到/proc/1/fd/1和/proc/fd/2(对于stderr)完全有效。谢谢大卫。
然而,这是违反直觉的。文件系统节点/dev/stdout和/dev/stderr已经存在于/proc/proc/1/fd/1和/proc/fd/fd/2的符号链接中,独立于cron。为什么不
cmd&gt; /dev/stdout
和cmd&gt; /proc/1/fd/1
在crontab中可以互换吗?@DavidMaze answered this in his comment (above - can't find a link to it). Redirecting to /proc/1/fd/1 and /proc/1/fd/2 (for stderr) totally works. Thank you, David.
Nevertheless, that's counterintuitive. The filesystem nodes /dev/stdout and /dev/stderr already exist as symlinks that point to /proc/1/fd/1 and /proc/1/fd/2, respectively, independent of cron. Why wouldn't
cmd > /dev/stdout
andcmd > /proc/1/fd/1
be interchangeable in a crontab?cron
是一段时间以前写的。预计,它不是docker
friendly。它希望任务不会产生输出。如果他们这样做,那被认为是错误,cron
试图给负责人发送电子邮件。有一些技巧可以使cron
任务的输出在docker logs
中可以看到,但是为什么不选择docker
docker -friendlycron
实现?其中之一是
supercronic
:docker-compose.yml:
dockerfile
:crontab
:a 要点提供更多信息。
另一个好的是 noreflow noreferrer“>
,但它使用yaml。
yacron
yacronofelia
似乎可以专注于在单独的容器中运行任务。这可能不是一个缺点,但我不确定为什么要这样做。
但是,如果您坚持传统的内容,可以在我的其他答案。
cron
was written quite a while a ago. And expectedly, it's not, say,docker
-friendly. It expects tasks to produce no output. And if they do, that is considered an error, andcron
tries to email the responsible person about it. There are some tricks to makecron
tasks' output to be seen indocker logs
, but why not choose adocker
-friendlycron
implementation?One of which is
supercronic
:docker-compose.yml
:Dockerfile
:crontab
:A gist with a bit more info.
Another good one is
yacron
, but it uses YAML.ofelia
can be used, but they seem to focus on running tasks in separate containers. Which is probably not a downside, but I'm not sure why I'd want to do that.But if you insist on traditional ones, you can find a couple in my other answer.
我重新考虑,并决定将克朗放在码头组的容器中是“反模式”。一方面,运行容器时“只能工作”的服务都很容易包装,但是如果我发生任何事情,那么接管的人可能很难弄清楚如何停止重复出现的任务(我网络工程师团队中唯一的开发人员和Docker用户)。相反,我只在团队使用的主机帐户中使用crontab,然后将容器的stderr重定向到主机上的日志文件。这样,对于那些知道在哪里看的人来说,一切都很容易找到。
I reconsidered and decided that putting cron in a Docker container was an “anti-pattern”. On the one hand, it’s tempting to package it all as a service that “just works” when you run the container, but if anything happened to me it might be hard for whoever takes over to figure out how to stop a recurring task (I’m the only developer and Docker user in a team of network engineers). Instead, I just use crontab in a host account used by my team, and redirect the container’s stderr to a log file on the host. That way everything can be found easily for those who know where to look.