2015-01-05 65 views
21

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

谢谢!

+1

这个职位似乎回答这个问题http://stackoverflow.com/questions/26822067/running-cron-python-jobs-within-docker – user2915097

回答

3

通过使用wrapper 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 

这是基于一个伟大的博客文章的地方,但我失去了联系。

2

环境已设置,但cron作业不可用。为了解决这个问题,你可以做两个简单的事情

1)保存ENV到一个文件中的入口点或CMD

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

2)然后读取ENV到您的cron命令是这样的:

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

当env值包含诸如空格或管道的字符时,这将不起作用 –

+0

您需要正确地使用空格或管道转义env vars。 – GDorn

19

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

  1. 设置你的cron容器
  2. 开始或切入点shell脚本设为第一线执行printenv | grep -v "no_proxy" >> /etc/environment

这里的窍门是/etc/environment文件。当容器被建立时,那个文件是空的,我认为是有意的。我在cron(8)的手册页中找到了该文件的参考。在查看所有版本的cron之后,它们全都隐藏到/etc/?文件中,您可以使用该文件将环境变量提供给子进程。

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

这里是我的entrypoint.sh文件以供参考,我的容器是debian:jessie base image。

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

cron -f 

而且,这一招与被时,docker run命令设置环境变量,甚至工作。

+1

printenv>/etc/environment是4天后为我工作的唯一一种实验各种选项的工具!谢谢! – Deko

+0

使用“/ etc/environment”为我工作,但请注意,读取此文件对于cron不是标准行为 - 只有在安装了pam cron模块后才能正常工作,请参阅https://askubuntu.com/a/ 700126 – llmora

+0

注意使用'/ etc/environment'文件的限制,因为不可能转义评论符号'#',所以你不能在它的变量值中使用它... – AuHau

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,依此类推。

2

我会建议使用declare导出您的环境,避免(在一个包装脚本这可能是由其中的一个被称为用CMD或入口点或直接)逃逸问题:

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