skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    @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 and cmd > /proc/1/fd/1 be interchangeable in a crontab?


  2. 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, and cron tries to email the responsible person about it. There are some tricks to make cron tasks’ output to be seen in docker logs, but why not choose a docker-friendly cron implementation?

    One of which is 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
    

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search