通过docker日志查看cron输出,无需使用额外的文件

ztigrdn8  于 2023-10-16  发布在  Docker
关注(0)|答案(7)|浏览(132)

我在Docker容器中运行“cron”。
每天都有一个脚本被执行。
这个脚本的输出,我想看到通过“docker日志“
PID为0的进程是我容器中的cron守护进程。Entrypoint在前台启动cron:

/usr/sbin/crond -f

我理解,我可以将脚本输出重定向到文件“path/to/logs”

07 2 * * * /data/docker/backup_webserver/backupscript.sh >> path/to/logs

并按如下方式启动容器以查看日志

"tail -f path/to/logs"

但是,文件“path/to/logs”将在容器运行时增长。

是否有可能从crontab直接登录到“docker logs”?

a6b3iqyw

a6b3iqyw1#

将您的cron文件更改为以下格式

07 2 * * * /data/docker/backup_webserver/backupscript.sh > /dev/stdout

这将确保日志进入容器输出

sg24os4d

sg24os4d2#

**Alpine:**无需重定向

  • 使用默认的cron实用程序(busybox)*

Dockerfile

FROM alpine:3.7

# Setting up crontab
COPY crontab /tmp/crontab
RUN cat /tmp/crontab > /etc/crontabs/root

CMD ["crond", "-f", "-l", "2"]

crontab

* * * * * echo "Crontab is working - watchdog 1"

Centos:

* 重定向到crontab声明行中的/proc/1/fd/1 *

Dockerfile

FROM centos:7

RUN yum -y install crontabs

ADD crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab
RUN crontab /etc/cron.d/crontab

CMD ["crond", "-n"]

crontab

* * * * * echo "Crontab is working - watchdog 1" > /proc/1/fd/1

zwghvu4y

zwghvu4y3#

@mcfedr是正确的,但我花了一段时间才理解它,它是一个带有变量和一些与设置cron相关的额外代码的一行程序。
这可能更容易阅读。它帮助我把它写得很清楚。

# Create custom stdout and stderr named pipes
mkfifo /tmp/stdout /tmp/stderr
chmod 0666 /tmp/stdout /tmp/stderr

# Have the main Docker process tail the files to produce stdout and stderr 
# for the main process that Docker will actually show in docker logs.
tail -f /tmp/stdout &
tail -f /tmp/stderr >&2 &

# Run cron
cron -f

然后,在你的cron中写入这些管道:

* * * * * /run.sh > /tmp/stdout 2> /tmp/stderr
0ve6wy6x

0ve6wy6x4#

fifo是一种方法,它也很有用,因为它允许不以root身份运行的cron任务写入输出。
我使用的CMD沿着这些线路

ENV LOG_STREAM="/tmp/stdout"
CMD ["bash", "-o", "pipefail", "-c", "mkfifo $$LOG_STREAM && chmod 777 $$LOG_STREAM && echo -e \"$$(env | sed 's/=\\(.*\\)/=\"\\1\"/')\n$$(cat /etc/cron.d/tasks)\" > /etc/cron.d/tasks && cron -f | tail -f $$LOG_STREAM"]

/etc/cron.d/tasks中的任务

* * * * */10 www-data echo hello >$LOG_STREAM 2>$LOG_STREAM

我还在tasks启动时预先添加了env,这样它对任务是可见的,因为cron不会自己传递它。需要sed是因为crontab格式要求对env变量加引号--至少它要求对空变量加引号,如果你有一个没有引号的空变量,它将无法运行任务。

dgtucam1

dgtucam15#

对于基于Debian的镜像,下面的Dockerfile适合我(注意,与用户crontab文件相比,/etc/crontab的格式略有不同):

FROM debian:buster-slim

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

RUN echo "* * * * * root echo 'Crontab is working - watchdog 1' > /proc/1/fd/1 2>/proc/1/fd/2" > /etc/crontab

CMD ["cron", "-f"]
w1e3prcc

w1e3prcc6#

你可以使用FIFO。

mkfifo path/to/logs

当进程通过FIFO交换数据时,内核传递所有数据而不将其写入文件系统。因此,特殊FIFO在文件系统上没有内容;文件系统条目仅用作参考点,使得进程可以使用文件系统中的A来访问管道。
man fifo

b1payxdu

b1payxdu7#

要将crond运行的命令的输出(stdout + stderr)获取到docker日志中,请按以下方式运行命令:

command 2>/proc/1/fd/2 | tee -a /proc/1/fd/1

2>/proc/1/fd/2command的stderr输出发送到docker容器的输出,而不将其从stderr更改为stdout。
tee -a /proc/1/fd/1command的stdout发送到docker容器的输出,并将其输出到标准输出(就像运行command时没有任何添加一样)。
为什么使用tee?它使整个字符串(cron作业)更适合调试:如果您只是复制它并粘贴到控制台(终端)并执行,您将在控制台(终端)和Docker容器输出(日志)中看到command输出。

相关问题