Comme l'a dit @Seamus, 99% de mes problèmes de crontab viennent du fait que j'ai des variables d'environnement différentes ou des PATH
donc crontab ne peut pas trouver le script et il échoue silencieusement. Par conséquent, ma solution était d'écrire un script enveloppant qui :
- Définit le
PATH
variable au même que celui auquel je suis habitué.
- Définit mon
PYTHONPATH
à mon modèle personnalisé pour inclure toutes mes fonctions courantes.
- Change le
DISPLAY
ET DBUS
variables pour que les applications graphiques comme les messages de notification et d'envoi soient effectivement affichés à l'écran.
- Change le répertoire de travail actuel pour le même que celui du script. (Si applicable)
- Lance le script avec
nice ionice -c3
pour économiser les ressources.
- Enregistre le
stdout
y stderr
du script dans le répertoire "logs" de sorte que lorsque quelque chose ne va pas, je puisse réellement trouver ce qui s'est passé.
Maintenant, si je veux lancer un script, il suffit d'éditer mycrontab avec crontab -e pour :
mm hh * * * /path-to.../cron.launcher.py script.name.sh
et il exécute le script comme si j'essayais de le faire depuis le terminal sans aucune aggravation. A l'origine, il s'agissait d'un script BASH, mais il était bloqué par les arguments contenant des espaces, alors j'ai tout réécrit en Python. Il lancera même des applications GUI dans l'espace utilisateur :
#!/usr/bin/python3
# Runtime directories:
SYSPATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
PYTHONPATH = ""
################################################################################
import os
import time
import sys
import subprocess
# Get username passed by crontab
user = os.environ['LOGNAME']
uid = subprocess.check_output(('id -u ' + user).split()).decode().strip()
gid = subprocess.check_output(('id -g ' + user).split()).decode().strip()
# Set Environmental Variables:
os.environ["PATH"] = SYSPATH
os.environ["PYTHONPATH"] = PYTHONPATH
os.environ["DISPLAY"] = ":0"
os.environ["XAUTHORITY"] = os.path.join('/home', user, '.Xauthority')
os.environ["DBUS_SESSION_BUS_ADDRESS"] = 'unix:path=' + os.path.join('/run/user', uid, 'bus')
os.environ["XDG_RUNTIME_DIR"] = os.path.join("/run/user", uid)
# Get args:
script = sys.argv[1]
args = sys.argv[2:]
name = os.path.basename(script)
basedir = os.path.dirname(sys.argv[0])
# Log dir
logdir = os.path.join(basedir, 'cron.logs')
log = os.path.join(logdir, name + '.' + str(int(time.time())) + '.log')
os.makedirs(logdir, exist_ok=True)
if not os.access(logdir, os.W_OK):
print("Can't write to log directory", logdir, file=sys.stderr)
sys.exit(1)
# If running as root, lock up any scripts so others can't edit them before root runs them.
if os.geteuid() == 0:
cron_log = os.path.join(logdir, 'cron.launcher.root.log')
for path in [script, sys.argv[0]] + list(filter(None, PYTHONPATH.split(':'))):
print("Setting permisisons for", path)
subprocess.run(('chown root -R ' + path).split(), stderr=subprocess.PIPE, check=False)
subprocess.run(('chmod og-w -R ' + path).split(), stderr=subprocess.PIPE, check=False)
else:
cron_log = os.path.join(logdir, 'cron.launcher.log')
cron_log = open(cron_log, 'a')
logger = lambda *args: cron_log.write(' '.join(map(str, args)) + '\n')
# Run the script
output = open(log, mode='w')
if os.path.exists(script):
os.chdir(os.path.dirname(script))
cmd = ['nice', 'ionice', '-c3'] + [script] + args
logger(time.strftime('\n%m-%d %H:%M', time.localtime()).lstrip('0'), user, "running:")
logger(cmd)
logger("in directory", os.getcwd(), "with log in", log)
start = time.time()
ret = subprocess.run(cmd, stdout=output, stderr=output, check=False)
# Cleanup
fmt = lambda num: ("{0:.3g}").format(num) if abs(num) < 1000 else str(int(num))
logger("Returned", ret.returncode, "after", fmt(time.time() - start), 'seconds')
output.close()
cron_log.close()
Assurez-vous de vérifier votre $PATH
y $PYTHONPATH
au cas où vous auriez besoin de les modifier pour qu'elles soient différentes.
4 votes
C'est une énorme copie de Raisons pour lesquelles la crontab ne fonctionne pas sur AskUbuntu.
1 votes
Il semble qu'Eric ait besoin d'avoir plus de réputation.
1 votes
Je viens de rejoindre Server Fault SE (donc seulement 101 rep), mais j'aimerais donner un -1 à cette question ! Cette question a-t-elle été posée uniquement pour obtenir des points de fidélité ? @IamtheMostStupidPerson Totalement d'accord avec vous...
0 votes
Ha ha ha :) Bien dit.
0 votes
Chers lecteurs : Si vous cherchez une bonne réponse pour vous aider à dépanner votre
cron
vous devriez peut-être chercher ailleurs. Je suis no en disant que la réponse de l'OP est dépourvu d'intelligence mais elle semble faire défaut à bien des égards. Il est également assez vieux maintenant. Il est censé être largement copié, et il y a maintenant 34 révisions contre lui - ce qui ne veut pas dire qu'il n'a pas été révisé. nécessairement Ce sont de mauvaises choses, mais si vous considérez le fait que l'OP (le bénéficiaire de la représentation) de cette réponse n'a contribué qu'à un grand total de 115 caractères (tout cela dans une période de deux heures) de ces modifications, vous commencez à vous demander...