J'ai récemment essayé d'exécuter un travail cron à partir d'un conteneur de docker lié et j'ai rencontré un problème. Mon conteneur docker principal est lié à un conteneur postgres et son numéro de port est défini en tant que variable d'environnement par docker lors de la création des conteneurs. Cette variable d'environnement n'est définie ni dans ~/.profile ni dans aucun autre fichier source que je pourrais charger lors de l'exécution de mon travail cron. Comment puis-je accéder à ces variables d'environnement à partir de mon travail cron?
Merci!
J'ai rencontré ce même problème. J'ai un conteneur Docker qui exécute cron pour exécuter périodiquement certains scripts Shell. Moi aussi, j'ai eu du mal à comprendre pourquoi mes scripts s'exécutaient correctement lorsque je les exécutais manuellement dans le conteneur. J'ai essayé toutes les astuces de la création d'un script Shell qui s'exécutait en premier pour définir l'environnement, mais ils ne m'ont jamais fonctionné (le plus souvent, j'ai mal agi). Mais j'ai continué à chercher et j'ai trouvé ça et ça fonctionne.
printenv | grep -v "no_proxy" >> /etc/environment
L'astuce ici est le fichier /etc/environment
. Lorsque le conteneur est construit, ce fichier est vide, je pense exprès. J'ai trouvé une référence à ce fichier dans les pages de manuel de cron (8) . Après avoir examiné toutes les versions de cron, elles ont toutes échappé à un fichier /etc/?
que vous pouvez utiliser pour alimenter des variables d'environnement avec des processus enfants.
Notez également que j'ai créé mon conteneur Docker pour exécuter cron au premier plan, cron -f
. Cela m'a aidé à éviter d'autres astuces avec tail
pour garder le conteneur ouvert.
Voici mon fichier entrypoint.sh pour référence et mon conteneur est une image de base debian: jessie.
printenv | grep -v "no_proxy" >> /etc/environment
cron -f
En outre, cette astuce fonctionnait même avec les variables d'environnement définies lors des commandes docker run
.
Je recommanderais d'utiliser declare
pour exporter votre environnement et éviter les problèmes d'échappement (en utilisant CMD ou ENTRYPOINT ou directement dans un script d'encapsulation pouvant être appelé par l'un d'eux):
declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env
Grep -v se charge de filtrer les variables en lecture seule.
Vous pouvez plus tard facilement charger cet environnement comme ceci:
Shell=/bin/bash
BASH_ENV=/container.env
* * * * * root /test-cron.sh
Vous pouvez ajouter les variables d'environnement système au sommet d'un fichier crontab en utilisant un script shell wrapper pour exécuter le démon cron. L’exemple suivant est tiré de CentOs 7,
Dans le fichier de docker
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
Ceci est basé sur un bon article de blog quelque part, mais j'ai perdu le lien.
L'environnement est défini, mais n'est pas disponible pour le travail cron. Pour résoudre ce problème, vous pouvez faire ces deux choses simples
1) Enregistrez l’env dans un fichier de votre ENTRYPOINT ou de votre CMD
CMD env > /tmp/.MyApp.env && /bin/MyApp
2) Lisez ensuite env dans votre commande cron comme ceci:
0 5 * * * . /tmp/.MyApp.env; /bin/MyApp
Pour échapper à tout caractère étrange qui pourrait casser votre script et selon le raisonnement de Réponse de Mark , ajoutez cette ligne à votre entrypoint.sh
:
env | sed -r "s/'/\\\'/gm" | sed -r "s/^([^=]+=)(.*)\$/\1'\2'/gm" \ > /etc/environment
Ainsi, si vous avez une variable telle que affinity:container==My container's friend
, elle sera convertie en affinity:container='=My container\'s friend
et ainsi de suite.