我最近尝试在链接的docker容器中运行cron作业并遇到问题。我的主docker容器链接到postgres容器,其端口号在创建容器时由docker设置为环境变量。此环境变量未在〜/ .profile或运行我的cron作业时可以加载的任何其他源文件中设置。那我如何从我的cron作业中访问这些环境变量呢?
谢谢!
答案 0 :(得分:39)
我遇到了同样的问题。我有一个运行cron的docker容器,可以定期执行一些shell脚本。当我在容器内手动执行它们时,我也很难找到为什么我的脚本运行正常。我尝试了创建一个首先运行以设置环境的shell脚本的所有技巧,但它们从来没有为我工作(很可能我做错了)。但是我继续寻找并发现了它,它确实有效。
printenv | grep -v "no_proxy" >> /etc/environment
这里的诀窍是/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)