【问题标题】:See cron output via docker logs, without using an extra file通过 docker 日志查看 cron 输出,无需使用额外文件
【发布时间】: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 是唯一有效的方法。

标签: docker logging


【解决方案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
      

      【讨论】:

      • 谢谢你 - 我能够理解逐行细分 - 它有效 ?
      猜你喜欢
      • 2016-09-08
      • 2017-01-03
      • 1970-01-01
      • 2020-07-13
      • 2022-10-15
      • 2022-10-13
      • 2017-10-30
      • 2010-09-07
      • 2021-04-06
      相关资源
      最近更新 更多