J'ai besoin de commencer un cronjob tous les jours, mais une heure plus tard chaque jour. Ce que j'ai jusqu'à présent fonctionne pour la plupart, sauf pour 1 jour de l'année:
0 0 * * * sleep $((3600 * (10#$(date +\%j) \% 24))) && /usr/local/bin/myprog
Lorsque le jour de l'année est 365, le travail commencera à 5h00, mais le lendemain (sans compter une année bissextile) aura un jour de l'année égal à 1, donc le travail commencera à 1h00. Comment puis-je me débarrasser de cette valise d'angle?
Réponses:
Ma solution préférée serait de démarrer le travail toutes les heures, mais de faire vérifier le script lui-même s'il est temps de l'exécuter et de le quitter sans rien faire 24 fois sur 25.
crontab:
en haut de
myprog
:Si vous ne voulez pas apporter de modifications au script lui-même, vous pouvez également mettre la vérification "time to run" dans l'entrée crontab mais cela crée une longue ligne inesthétique:
la source
date
retour du noyau était1ms
antérieure à l'heure à laquelle vous vous attendiez à ce que le script s'exécute, la vérification donnerait un résultat incorrect.ntpd
, il s'efforce de ne faire que tourner l'horloge, pas de la sauter, spécifiquement pour éviter ce genre de problème, mais vous avez raison, il (ountpdate
) peut parfois sauter le temps en arrière. Quant àcron
mal calculer son retard de sommeil, je suis presque sûr que ce serait considéré comme un bug! Pourtant, le point est pris, et une solution de contournement serait de planifier le travail 30 minutes après l'heure, ce qui est moins susceptible de causer le problème ... Ou ajouter ± 1800 dans l'expression arithmétique avant de prendre le mod 3600 de reamainder.Si votre système a systemd, vous pouvez utiliser des événements de temporisation pour cela. Définissez simplement un nouveau service , qui devrait contenir la commande / tâche que vous souhaitez exécuter, puis créez un événement de minuterie avec l'
OnUnitActiveSec
option:Utilisez le même nom pour les fichiers, sauf qu'au lieu d'
.service
utiliser.timer
.Synthétiser:
job.service
dans le/etc/systemd/system/
répertoire.systemctl status job.service
.job.timer
dans/etc/systemd/system/
.Remplissez-le avec les informations requises:
systemctl list-timers
la source
Si cela ne vous dérange pas d'utiliser autre chose que cronjobs, je suggérerais l'utilitaire moins connu
at
. Écrivez simplement un script wrapper qui se planifie pour s'exécuter en 25 heures, puis appelle votre programme. Cela semble être la solution la plus propre.Par exemple, vous pouvez écrire ceci dans ~ / script.sh:
Et puis exécutez simplement
bash ~/script.sh
une fois.Merci à @HalosGhost pour l'idée de planifier le travail une fois en 25 heures.
la source
at
à cette fin: (1) si le travail ne s'exécute pas correctement une seule fois, il échoue également probablement à se replanifier et ensuite non seulement la prochaine exécution, mais toutes les futures exécutions sont effectivement annulées jusqu'à ce qu'un humain le remarque, et (2) étant donné que le travail prend un certain temps non nul pour s'exécuter, en utilisant lenow + 25 hours
moyen naïf , il s'exécutera quelques secondes (ou plus) plus tard à chaque fois, et si ce décalage s'accumule au fil du temps, le rendant éventuellement exécuté complètement à tort temps.at
est limitée à quelques minutes et démarre tous les travaux à [heure]: 00.at
travail première chose que dans le scénario à éviter ces problèmes. Néanmoins, si une erreur se produit, toute la chaîne est rompue, ce qui peut ou non être souhaité: si le cas d'utilisation est "ne l'exécuter que lorsqu'il fonctionne", le non-redémarrage est une fonctionnalité intéressante. Mais si le cas d'utilisation est "toujours exécuté, même si le dernier a échoué", ceat
n'est pas le bon outil.