J'ai normalement plusieurs problèmes avec la façon dont cron exécute les scripts, car ils n'ont normalement pas été configurés dans mon environnement. Existe-t-il un moyen d'appeler bash (?) De la même manière que cron pour pouvoir tester les scripts avant de les installer?
Ajoutez ceci à votre cron:
30 08 * * * env > ~/cronenv
Après cela, faites ceci:
env - `cat ~/cronenv` /bin/sh
Cela suppose que votre cron exécute/bin/sh, la valeur par défaut, quel que soit le shell par défaut de l'utilisateur.
Cron fournit uniquement cet environnement par défaut:
HOME
répertoire de base de l'utilisateurLOGNAME
login de l'utilisateurPATH=/usr/bin:/usr/sbin
Shell=/usr/bin/sh
Si vous avez besoin de plus d’informations, vous pouvez créer un script dans lequel vous définissez votre environnement avant la table de planification dans la crontab.
Couple d'approches:
Exporter cron env et le source:
Ajouter
* * * * * env > ~/cronenv
dans votre crontab, laissez-le fonctionner une fois, éteignez-le, puis exécutez
env - `cat ~/cronenv` /bin/sh
Et vous êtes maintenant dans une session sh
qui a l'environnement de cron
Apportez votre environnement à cron
Vous pouvez passer au-dessus de l'exercice et juste faire un . ~/.profile
devant votre tâche cron, par exemple.
* * * * * . ~/.profile; your_command
Utiliser l'écran
Les deux solutions ci-dessus échouent toujours car elles fournissent un environnement connecté à une session X en cours d'exécution, avec un accès à dbus
etc. Par exemple, sous Ubuntu, nmcli
(Network Manager) fonctionnera dans les deux approches ci-dessus, mais échouera toujours dans cron.
* * * * * /usr/bin/screen -dm
Ajoutez la ligne ci-dessus à cron, laissez-le fonctionner une fois, éteignez-le. Connectez-vous à votre session d'écran (écran -r). Si vous vérifiez que la session d'écran a été créée (avec ps
), sachez qu'elles sont parfois en majuscule (par exemple ps | grep SCREEN
).
Maintenant, même nmcli
et similaire échoueront.
Tu peux courir:
env - your_command arguments
Cela exécutera votre_commande avec un environnement vide.
En fonction du shell du compte
Sudo su
env -i /bin/sh
ou
Sudo su
env -i /bin/bash --noprofile --norc
De http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html
Six ans plus tard, le problème de l'inadéquation de l'environnement est l'un des problèmes résolus par systemd
"timers" en remplacement de cron. Que vous exécutiez le "service" systemd à partir de la CLI ou via cron, il reçoit exactement le même environnement, évitant ainsi le problème de non-concordance de l'environnement.
Le problème le plus courant entraînant l'échec des tâches cron lorsqu'elles sont passées manuellement est la valeur par défaut restrictive $PATH
définie par cron, ce qui est le cas sous Ubuntu 16.04:
"/usr/bin:/bin"
En revanche, le $PATH
par défaut défini par systemd
sur Ubuntu 16.04 est:
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
Donc, il y a déjà une meilleure chance qu'un minuteur systemd trouve un binaire sans autre problème.
L'inconvénient des minuteries systemd, c'est qu'il leur reste un peu plus de temps pour les configurer. Vous créez d’abord un fichier "service" pour définir ce que vous voulez exécuter, puis un fichier "timer" pour définir la planification de son exécution, puis "activer" le timer pour l’activer.
Créez un travail cron qui exécute env et redirige stdout vers un fichier . Utilisez le fichier à côté de "env -" pour créer le même environnement qu'un travail cron.
N'oubliez pas que puisque le parent de cron est init, il exécute des programmes sans terminal de contrôle. Vous pouvez simuler cela avec un outil comme celui-ci:
Par défaut, cron
exécute ses travaux en utilisant l’idée que votre système a de sh
. Il peut s'agir du shell Bourne ou de la variable dash
, ash
, ksh
ou bash
(ou une autre) liée à sh
(et s'exécutant en mode POSIX).
La meilleure chose à faire est de vous assurer que vos scripts ont ce dont ils ont besoin et de supposer que rien ne leur est fourni. Par conséquent, vous devez utiliser les spécifications complètes du répertoire et définir vous-même les variables d'environnement telles que $PATH
.
Un autre moyen simple que j'ai trouvé (mais qui peut être sujet à des erreurs, je suis toujours en train de tester) est de générer les fichiers de profil de votre utilisateur avant votre commande.
Éditer un script /etc/cron.d/:
* * * * * user1 comand-that-needs-env-vars
Se transformerait en:
* * * * * user1 source ~/.bash_profile; source ~/.bashrc; comand-that-needs-env-vars
Sale, mais le travail a été fait pour moi. Existe-t-il un moyen de simuler un login? Juste une commande que vous pourriez exécuter? bash --login
n'a pas fonctionné. Cela semble être la meilleure solution.
EDIT: Cela semble être une solution solide: http://www.epicserve.com/blog/2012/feb/7/my-notes-cron-directory-etccrond-ubuntu-1110/
* * * * * root su --session-command="comand-that-needs-env-vars" user1 -l
Answer https://stackoverflow.com/a/2546509/5593430 montre comment obtenir l'environnement cron et l'utiliser pour votre script. Sachez toutefois que l’environnement peut varier en fonction du fichier crontab que vous utilisez. J'ai créé trois entrées cron différentes pour sauvegarder l'environnement via env > log
. Ce sont les résultats sur un Amazon Linux 4.4.35-33.55.amzn1.x86_64.
MAILTO=root
Shell=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
PWD=/
LANG=en_US.UTF-8
SHLVL=1
HOME=/
LOGNAME=root
_=/bin/env
crontab -e
)Shell=/bin/sh
USER=root
PATH=/usr/bin:/bin
PWD=/root
LANG=en_US.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/env
MAILTO=root
Shell=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
_=/bin/env
PWD=/
LANG=en_US.UTF-8
SHLVL=3
HOME=/
LOGNAME=root
Plus important encore, PATH
, PWD
et HOME
diffèrent. Assurez-vous de les définir dans vos scripts cron pour qu'ils reposent sur un environnement stable.