J'ai défini la variable "Shell" dans le fichier/etc/crontab:
[martin@martin ~]$ grep Shell /etc/crontab
Shell=/usr/local/bin/bash
[martin@martin ~]$ file /usr/local/bin/bash
/usr/local/bin/bash: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked (uses shared libs), for FreeBSD 8.0 (800107), stripped
[martin@martin ~]$
De plus, tous mes scripts dans le fichier/etc/crontab sont démarrés sous l'utilisateur "martin". Cependant / home/martin/.bash_profile (pour le shell de connexion) et / home/martin/.bashrc (pour le shell sans journalisation) contiennent certaines variables qui sont ignorées en cas du travail cron, mais sont utilisés dans le cas où je me connecte à la machine via SSH ou ouvre une nouvelle session bash. Pourquoi cron ignore ces variables? Cron n'exécute-t-il pas simplement "/ usr/local/bin/bash my-script.sh" avec les autorisations de l'utilisateur "martin"?
Vous pouvez rechercher le fichier souhaité en haut du script ou au début du travail pour l'utilisateur qui exécute le travail. La commande "source" est intégrée. Vous feriez la même chose si vous apportiez des modifications à ces fichiers pour charger les modifications.
* * * * * source /home/user/.bash_profile; <command>
ou
#!/bin/bash
source /home/user/.bash_profile
<commands>
Parce que ce n'est pas un Shell interactif. La même chose se produit lorsque vous ouvrez certains terminaux.
Jetez un œil à cette question: Qu'est-ce que le fichier .bashrc? | Super User
Et aussi à celui-ci:
Quelle est la différence entre .bashrc, .bash_profile et .environment? | Stack Overflow
Différents scripts se déclenchent selon que la connexion est un shell de connexion (ou non), un shell interactif (ou non), ou les deux.
Si vous voulez faire bashrc, vous devrez faire ce changement:
Lorsque Bash est démarré de manière non interactive, pour exécuter un script Shell, par exemple, il recherche la variable BASH_ENV dans l'environnement, développe sa valeur si elle y apparaît et utilise la valeur développée comme nom d'un fichier à lire et à exécuter. . Bash se comporte comme si la commande suivante était exécutée:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
mais la valeur de la variable PATH n'est pas utilisée pour rechercher le nom de fichier.
Comme indiqué ci-dessus, si un shell non interactif est appelé avec le
--login
, Bash tente de lire et d'exécuter des commandes à partir des fichiers de démarrage du shell de connexion.
Source: Fichiers de démarrage Bash | Manuel de référence Bash | gnu.org
Vous ne pourrez peut-être pas exécuter source
si le shell sh
est utilisé. Cela peut être changé en ajoutant la ligne suivante dans votre crontab:
Shell=/bin/bash
* * * * * source "/root/.bashrc"; <command>
Vous pouvez également spécifier l'environnement:
BASH_ENV="/root/.bashrc"
* * * * * <command>
ou vous pouvez utiliser votre /home/user/.bashrc
s'il s'agit d'un travail cron utilisateur (par exemple crontab -e
).
Notez que .bash_profile
peut remplacer .bashrc
, s'il existe.
Autre élément susceptible d'interférer avec l'approvisionnement de votre .bashrc
à partir d'un cronjob est tout contrôle effectué par ce fichier afin de détecter les shells interactifs.
Par exemple, sur Ubuntu 18.04, la valeur par défaut .bashrc
pour un utilisateur commence par ceci:
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
et donc l'approvisionnement ne fera rien d'utile car il se fermera immédiatement.
Vous pouvez invoquer bash avec le -l
option, comme ceci:
* * * * * /bin/bash -l /path/to/script arg1 arg2
Le -l
l'option fait de bash un login Shell. Ainsi, il lira le .bash_profile
. Il ne lira pas le .bashrc
sauf si elle est explicitement fournie par .bash_profile
. En effet, les shells non interactifs ne lisent pas automatiquement .bashrc
. Mais vous ne devriez pas avoir besoin de .bashrc
pour un travail cron car .bashrc
sert à définir des éléments utiles pour un shell interactif .
Variations:
Si bash est sur le PATH, il n'est pas nécessaire de spécifier un chemin absolu:
* * * * * bash -l /path/to/script arg1 arg2
Une optimisation serait de remplacer le shell actuel en utilisant exec
:
* * * * * exec bash -l /path/to/script arg1 arg2
bash
agit différemment que ce soit un Shell ou un normal langage de programmation (comme Perl
ou python
).
De par leur conception, les paramètres de ~/.bash_profile
, ~/.bashrc
, etc. permettent aux utilisateurs de définir les choses lorsque bash
joue le rôle d'un shell (shell de connexion, shell interactif). Pensez à l'environnement que vous avez dans un xterm
(shell interactif) ou dans des sessions ssh
(shell de connexion) ou dans des consoles (shell de connexion).
D'autre part, bash
est également un puissant langage de programmation –pensez à de nombreux scripts de gestion des services dans systemd
– qui nécessitent un style de travail différent. Par exemple, lorsqu'un développeur écrit un script système ou un programme bash
, il/elle n'aimera pas source _ ~/.bash_profile
automatiquement. C'est un programme normal, pas un Shell. Un programme normal (y compris les programmes bash
) aurait naturellement hérité les paramètres de l'environnement de travail actuel (Shell), mais pas défini eux.
Si nous écrivons un programme pour cron
dans bash
–il se trouve simplement être écrit dans bash
; en fait, nous pouvons l'écrire dans python
ou Perl
ou tout autre langage de programmation - alors nous pouvons avoir une option pour les sources bash
's ~/.bash_profile
(lire: paramétrage du shell de l'utilisateur, qui se trouve être le même langage que votre langage de programmation):
[ -f /home/user/.bash_profile ] && . /home/user/.bash_profile
Cependant, que se passe-t-il si cet utilisateur particulier n'utilise pas bash
comme shell? Il/elle peut utiliser zsh
, ksh
, fish
, etc. Ainsi, cette pratique ne fonctionnerait pas vraiment lors de l'écriture d'un programme à usage public.
Vous pouvez donc source ~/.bash_profile
si vous pensez que cela fonctionnera. Mais, ici, il ne s'agit pas de savoir si nous sommes en mesure de trouver un fichier, il s'agit de savoir comment les choses devraient fonctionner dans le système: le concept de conception. En bref: nous devrions voir bash
comme quelque chose ayant 2 rôles: Shell et langage de programmation. Ensuite, tout sera beaucoup plus facile à comprendre.
J'ai eu le même problème lors de l'exécution d'une application de noeud à partir de cron qui utilise NVM.
par exemple: * * * * * /bin/bash -lc '/home/user/myapp.sh restart'
Si cela ne fonctionne pas, essayez de définir la variable de chemin dans crontab
41 7 * * * /bin/bash -lc "PATH=$PATH:/home/user/.nvm/versions/node/v8.10.0/bin && /home/user/script.sh restart "