Comment simuler l’environnement avec lequel cron exécute un script?

J’ai normalement plusieurs problèmes avec la façon dont cron exécute les scripts car ils n’ont normalement pas la configuration de mon environnement. Existe-t-il un moyen d’invoquer bash (?) De la même manière que cron afin de 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, qui est la valeur par défaut quel que soit le shell par défaut de l’utilisateur.

Cron fournit uniquement cet environnement par défaut:

  • Répertoire personnel de l’utilisateur HOME
  • Identifiant de l’utilisateur LOGNAME
  • PATH=/usr/bin:/usr/sbin
  • SHELL=/usr/bin/sh

Si vous avez besoin de plus, vous pouvez créer un script dans lequel vous définissez votre environnement avant la table de planification dans la crontab.

Quelques approches:

  1. Exporter cron env et le source:

    Ajouter

     * * * * * env > ~/cronenv 

    à 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

  2. Apportez votre environnement à cron

    Vous pouvez sauter ci-dessus et juste faire un . ~/.profile . ~/.profile devant votre travail cron, par exemple

     * * * * * . ~/.profile; your_command 
  3. Utiliser l’écran

    Les deux solutions ci-dessus échouent toujours dans la mesure où elles fournissent un environnement connecté à une session X en cours, avec access à dbus etc. Par exemple, sur Ubuntu, nmcli (Network Manager) fonctionnera dans les deux approches ci-dessus.

     * * * * * /usr/bin/screen -dm 

    Ajoutez la ligne ci-dessus à cron, laissez-la s’exécuter une fois, désactivez-la. Connectez-vous à votre session d’écran (screen -r). Si vous vérifiez que la session d’écran a été créée (avec ps ), sachez qu’elle est parfois en majuscule (ex: ps | grep SCREEN )

    Maintenant, même nmcli et similaire échouera.

Tu peux courir:

 env - your_command arguments 

Cela exécutera votre_commande avec un environnement vide.

Selon le 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 les “minuteurs” de Systemd en tant que remplacement cron. Que vous exécutiez le “service” systemd depuis la CLI ou via cron, il reçoit exactement le même environnement, évitant le problème d’incompatibilité de l’environnement.

Le problème le plus courant pour faire échouer les tâches cron lorsqu’elles sont transmises manuellement est la valeur par défaut ressortingctive de $PATH définie par cron, à savoir sur Ubuntu 16.04:

 "/usr/bin:/bin" 

En revanche, la valeur par défaut de $PATH définie par systemd sur Ubuntu 16.04 est la suivante:

 "/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 fichier binary sans plus de problèmes.

L’inconvénient des timers systemd, c’est qu’il y a 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 et un fichier “timer” pour définir le planning sur lequel il doit être exécuté et enfin “activer” le timer pour l’activer.

Créez un travail cron qui exécute env et redirige stdout vers un fichier. Utilisez le fichier avec “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:

http://libslack.org/daemon/

Par défaut, cron exécute ses travaux en utilisant l’idée de sh de votre système. Cela peut être le shell ou le dash Bourne, ash , ksh ou bash (ou un autre) lié à sh (et s’exécutant en mode POSIX).

La meilleure chose à faire est de s’assurer que vos scripts ont ce dont ils ont besoin et de supposer que rien n’est prévu pour eux. Par conséquent, vous devez utiliser des spécifications de répertoire complètes et définir vous-même des variables d’environnement telles que $PATH .

Un autre moyen simple que j’ai trouvé (mais qui peut être source d’erreurs, je teste encore) consiste à rechercher les fichiers de profil de votre utilisateur avant votre commande.

Modifier 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 ça a fait le travail pour moi. Existe-t-il un moyen de simuler une connexion? Juste une commande que vous pourriez exécuter? bash --login n’a pas fonctionné. Il semble que ce serait la meilleure façon de faire si.

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 

Réponse https://stackoverflow.com/a/2546509/5593430 montre comment obtenir l’environnement cron et l’utiliser pour votre script. Mais sachez que l’environnement peut différer selon le 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 Amazon Linux 4.4.35-33.55.amzn1.x86_64.

1. Global / etc / crontab avec l’utilisateur root

 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 

2. crontab de l’utilisateur root ( 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 

3. Script dans /etc/cron.hourly/

 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 vous baser sur un environnement stable.

Je ne crois pas qu’il y en a; La seule façon de tester un job cron est de le configurer pour exécuter une minute ou deux dans le futur, puis d’attendre.