J'ai un script qui fonctionne lorsque je l'exécute à partir de la ligne de commande, mais lorsque je le planifie avec cron
j'obtiens des erreurs indiquant qu'il ne trouve pas de fichiers ou de commandes. Ma question est double:
Lorsque je planifie un travail cron à l'aide de crontab -e
, utilise-t-il mon ID utilisateur comme base pour ses autorisations? Ou utilise-t-il un ID utilisateur cron quelconque et ses autorisations associées?
Lorsqu'un travail cron est lancé, quel est le répertoire de travail? Est-ce le répertoire dans lequel je spécifie le script à exécuter ou un autre répertoire?
Voici mon travail cron:
15 7 * * * /home/xxxx/Documents/Scripts/email_ip_script.sh
Voici le script réel:
vIP_ADDR="`curl automation.whatismyip.com/n09230945.asp`"
echo "$vIP_ADDR"
sed "s/IPADDR/$vIP_ADDR/g" template.txt > emailmsg.txt
ssmtp [email protected] < emailmsg.txt
Voici les erreurs que j'obtiens lorsque je consulte le message mail
produit par cron
:
sed: can't read template.txt: No such file or directory
/home/xxxx/Documents/Scripts/email_ip_script.sh: line 15: ssmtp: command not found
Il ne peut pas trouver le template.txt
mais il réside dans le même répertoire que le script. Il ne peut pas non plus exécuter ssmtp
, mais je peux en tant qu'utilisateur. Que manque-t-il pour que cela fonctionne correctement?
Ajouter cd /home/xxxx/Documents/Scripts/
si vous souhaitez que votre travail s'exécute dans ce répertoire. Il n'y a aucune raison pour que cron passe à ce répertoire particulier. Cron exécute vos commandes dans votre répertoire personnel.
Quant à ssmtp
, il peut ne pas être dans votre PATH
par défaut. Le chemin par défaut de Cron dépend de l'implémentation, vérifiez donc votre page de manuel, mais selon toute vraisemblance, ssmtp
est dans /usr/sbin
qui n'est pas dans votre valeur par défaut PATH
, seulement celle de root.
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
15 7 * * * cd /home/xxxx/Documents/Scripts && ./email_ip_script.sh
Si votre cronjob est un script bash, ce qui suit sera CD à l'emplacement de votre script (en supposant que vous utilisez le chemin absolu dans votre définition de cron):
cd "$(dirname "$0")";
Pour répondre à la question 1: si vous exécutez crontab -e
en tant que votre propre utilisateur, les travaux seront planifiés dans la crontab de cet utilisateur et seront donc exécutés avec les autorisations de cet utilisateur.
Mais vous devez considérer que les travaux s'exécuteront dans un shell non interactif, ce qui signifie que $ PATH peut être différent de celui que vous avez lors de l'exécution du script à partir de la ligne de commande.
Il est préférable de toujours utiliser les chemins d'accès complets dans les scripts, surtout si vous prévoyez de les planifier via at/cron, etc.
Je recommanderais également d'utiliser des chemins d'accès complets à tous les fichiers pour éviter exactement les problèmes que vous voyez.
Pour éviter les conditions de concurrence et d'autres problèmes de sécurité, vous devez également utiliser mktemp
pour vous assurer que le fichier que vous lisez n'est modifié par rien en dehors de votre script.
Je changerais donc le script en quelque chose comme:
vIP_ADDR="`curl automation.whatismyip.com/n09230945.asp`"
echo "$vIP_ADDR"
mail_msg=`/bin/mktemp`
/bin/sed "s/IPADDR/$vIP_ADDR/g" /home/xxxx/Documents/Scripts/template.txt > $mailmsg
/path/to/ssmtp [email protected] < $mailmsg
/bin/rm $mailmsg
cron
exécute les travaux planifiés de chaque utilisateur en tant que cet utilisateur. Cela devrait nous suffire pour déterminer qu'il exécute vos scripts par rapport à votre répertoire personnel.
Si vous en avez besoin pour exécuter à partir d'un emplacement différent, utilisez simplement cd
dans votre script pour accéder à cet emplacement.
ssmtp
n'est probablement pas dans le CHEMIN par défaut de cron
(il est défini comme étant très étroit par conception sur la plupart des plates-formes). Vous pouvez soit spécifier le chemin d'accès complet à ssmtp
dans votre script, soit définir explicitement PATH dans a) votre fichier crontab, qui sera disponible pour tous vos scripts, ou b) dans chaque script.
Vérifiez ce thread comment vous pouvez facilement trouver l'environnement de cron, c'est beaucoup moins que ce à quoi vous êtes habitué dans un shell interactif. Le mieux est de supposer que rien n'a été défini et de le définir explicitement vous-même.
Le répertoire de travail par défaut de cron
lors de l'exécution du travail est le répertoire de base, généralement /home/your-user-name
.
Adopter @Kusalananda excellent commentaire.
Certaines personnes ont laissé entendre ou lié à cela, mais la meilleure façon de le savoir, car je ne le trouve pas dans les documents de l'homme pour ma distribution, est simplement d'ajouter ceci à un cron
* * * * * echo $PATH > /tmp/lolcronjobs
Dans mon cas, ubuntu utilise par défaut uniquement /usr/bin:/bin
ce qui a causé quelques problèmes.