通过 docker 日志查看 cron 输出,无需使用额外文件
Posted
技术标签:
【中文标题】通过 docker 日志查看 cron 输出,无需使用额外文件【英文标题】:See cron output via docker logs, without using an extra file 【发布时间】:2018-01-05 19:34:57 【问题描述】:我在 docker 容器中运行“cron”。 每天都会执行一个脚本。 我想通过“docker logs”查看此脚本的输出
PID 为 0 的进程是我容器中的 cron 守护进程。入口点在前台启动 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”?
【问题讨论】:
我创建了一个仓库来解决这个问题:github.com/tomsaleeba/alpine-cron-test。答案似乎是不添加任何额外的重定向,它会“正常工作”,至少对于我简单的echo
测试而言。
在我的情况下,This answer 是唯一有效的方法。
【参考方案1】:
将您的 cron 文件更改为以下
07 2 * * * /data/docker/backup_webserver/backupscript.sh > /dev/stdout
这将确保日志进入容器输出
【讨论】:
当使用crond -l 2 -f
开始时,这适用于Alpine
为什么会这样?我以为/dev/stdout
实际上会转到/proc/self/fd/1
,对于cron 启动的进程,这不会是docker 监控的/proc/1/fd/1
文件。
我认为这不会起作用,因为 /dev/stdout 是访问它的进程的 STDOUT 的链接。因此,通过执行 foo > /dev/stdout,您是在说“将我的 STDOUT 重定向到我的 STDOUT”。 Kinda 什么都不做 :-)。
添加到我自己的评论中,我认为 cron 正在收集作业的输出并将其传递给 its 标准输出,是码头工人监控。
@TomSaleeba,是的,因为重定向是在 cron 的进程中运行的,这就是为什么 stdout 只是 cron 的原因【参考方案2】:
你可以只使用 FIFO。
mkfifo path/to/logs
当进程通过 FIFO 交换数据时,内核将所有 数据而不将其写入文件系统。因此,FIFO 特殊具有 文件系统上没有内容;文件系统条目仅用于 参考点,以便进程可以使用 a 访问管道 文件系统。
man fifo
【讨论】:
【参考方案3】: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
我还在启动时将 env 添加到 tasks
,因此它对任务是可见的,因为 cron 不会自行传递它。 sed
是必需的,因为 crontab 格式需要引用环境变量 - 至少它需要引用空变量,并且如果您有一个没有引号的空变量,则无法运行任务。
【讨论】:
【参考方案4】: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
【讨论】:
我很好奇...为什么将 crontab 复制到 /tmp 然后再复制到 /etc/crontabs/root? Debian 应用补丁来取消标准输出,与 CentOS 类似:salsa.debian.org/debian/cron/-/blob/master/debian/patches/fixes/… 我猜 Alpine 是唯一不应用此补丁的人 我建议您在 CentOS 的答案中添加2>/proc/1/fd/2
以捕获发送到 stderr 的错误
你能告诉我这是什么意思吗:using the default cron utility (busybox)
我的ubuntu 有一个busybox 二进制文件/usr/bin/busybox
,其中包含一组小程序。我需要使用busybox appletname
来访问它们。你怎么能在busybox中引用你的crond
而不在你的命令中提到busybox
。【参考方案5】:
@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
【讨论】:
谢谢你 - 我能够理解逐行细分 - 它有效 ?以上是关于通过 docker 日志查看 cron 输出,无需使用额外文件的主要内容,如果未能解决你的问题,请参考以下文章
dockerdocker部署spring boot服务,但是docker logs查看容器输出控制台日志,没有日志打印,日志未打印,docker logs不打印容器日志