如何从Cron作业访问Docker set Environment Variables

时间:2015-01-05 00:10:24

标签: cron environment-variables docker

我最近尝试在链接的docker容器中运行cron作业并遇到问题。我的主docker容器链接到postgres容器,其端口号在创建容器时由docker设置为环境变量。此环境变量未在〜/ .profile或运行我的cron作业时可以加载的任何其他源文件中设置。那我如何从我的cron作业中访问这些环境变量呢?

谢谢!

8 个答案:

答案 0 :(得分:39)

我遇到了同样的问题。我有一个运行cron的docker容器,可以定期执行一些shell脚本。当我在容器内手动执行它们时,我也很难找到为什么我的脚本运行正常。我尝试了创建一个首先运行以设置环境的shell脚本的所有技巧,但它们从来没有为我工作(很可能我做错了)。但是我继续寻找并发现了它,它确实有效。

  1. 为您的cron容器设置启动或入口点shell脚本
  2. 将此作为执行printenv | grep -v "no_proxy" >> /etc/environment
  3. 的第一行

    这里的诀窍是/etc/environment文件。当容器构建成文件为空时,我是故意的。我在cron(8)的手册页中找到了对此文件的引用。在查看了cron的所有版本之后,他们都会找到一个/etc/?文件,您可以使用该文件将环境变量提供给子进程。

    另外,请注意我创建了我的docker容器以在前台运行cron cron -f。这有助于我避免使用tail运行的其他技巧来保持容器。

    这是我的entrypoint.sh文件供参考,我的容器是debian:jessie基本图像。

    printenv | grep -v "no_proxy" >> /etc/environment
    
    cron -f
    

    此外,即使使用docker run命令期间设置的环境变量,此技巧也能正常工作。

答案 1 :(得分:12)

我建议使用declare导出您的环境并避免转义问题(使用CMD或ENTRYPOINT或直接在其中一个可能调用的包装脚本中):

declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env

Grep -v负责过滤掉只读变量。

您可以稍后轻松加载此环境:

SHELL=/bin/bash
BASH_ENV=/container.env
* * * * * root /test-cron.sh

答案 2 :(得分:4)

灵感来自@Kannan Kumarasamy答案:

  for variable_value in $(cat /proc/1/environ | sed 's/\x00/\n/g'); do
    export $variable_value
  done

我无法确定pid1是什么进程,以及它在OS生存期内是否稳定。但由于它是第一个运行的进程,因此我想在容器内可以认为它是理所当然的,因为它是设置了所需env vars的进程。除非有些linux / docker文档证明这是完全可以的,否则请多加些盐。

答案 3 :(得分:3)

可以使用包装器shell脚本运行cron守护程序,将系统环境变量附加到crontab文件的顶部。以下示例来自CentOs 7,

在Dockerfile中

COPY my_cron /tmp/my_cron
COPY bin/run-crond.sh run-crond.sh
RUN chmod -v +x /run-crond.sh
CMD ["/run-crond.sh"]

run_cron.sh:

#!/bin/bash

# prepend application environment variables to crontab
env | egrep '^MY_VAR' | cat - /tmp/my_cron > /etc/cron.d/my_cron

# Run cron deamon
# -m off : sending mail is off 
# tail makes the output to cron.log viewable with the $(docker logs container_id) command
/usr/sbin/crond -m off  && tail -f /var/log/cron.log

这是基于一个很棒的博客文章,但我丢失了链接。

答案 4 :(得分:2)

已设置环境,但cron作业无法使用。要解决这个问题,你可以做这两件简单的事情

1)将env保存到ENTRYPOINT或CMD中的文件

CMD env > /tmp/.MyApp.env && /bin/MyApp

2)然后将env读入你的cron命令,如下所示:

0 5 * * * . /tmp/.MyApp.env; /bin/MyApp

答案 5 :(得分:0)

要转义任何可能破坏您的脚本的奇怪字符,并根据Mark's answer的推理,将此行添加到entrypoint.sh

env | sed -r "s/'/\\\'/gm" | sed -r "s/^([^=]+=)(.*)\$/\1'\2'/gm" \ > /etc/environment

这样,如果您有affinity:container==My container's friend之类的变量,它将转换为affinity:container='=My container\'s friend,依此类推。

答案 6 :(得分:0)

您可以运行以下命令

. <(xargs -0 bash -c 'printf "export %q\n" "$@"' -- < /proc/1/environ)

当您的环境变量带有特殊字符(例如' " =

时,这将非常有用)

答案 7 :(得分:0)

您应该在运行cronjobs之前导出环境变量。

其他解决方案也可以,但是当环境变量中包含任何特殊字符时,它们将失败。

我找到了解决方法:

eval $(printenv | awk -F= '{print "export " "\""$1"\"""=""\""$2"\"" }' >> /etc/profile)