Ok, j'ai donc un cron que je dois exécuter toutes les 30 secondes.
Voici ce que j'ai:
*/30 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''
Il fonctionne, mais est-ce que cela fonctionne toutes les 30 minutes ou 30 secondes?
De plus, j'ai lu que cron pourrait ne pas être le meilleur outil à utiliser si je l'exécute aussi souvent. Y a-t-il un autre meilleur outil que je peux utiliser ou installer sur Ubuntu 11.04 qui sera une meilleure option? Existe-t-il un moyen de corriger le cron ci-dessus?
ubuntu
cron
scheduled-tasks
Matt Elhotiby
la source
la source
Réponses:
Vous avez
*/30
dans le spécificateur de minutes - cela signifie chaque minute mais avec un pas de 30 (en d'autres termes, toutes les demi-heures). Étant donné quecron
cela ne se résume pas à des résolutions de moins d'une minute, vous devrez trouver un autre moyen.Une possibilité, bien que ce soit un peu compliqué (a) , est d'avoir deux tâches, une décalée de 30 secondes:
Vous verrez que j'ai ajouté des commentaires et formaté pour vous assurer qu'il est facile de les synchroniser.
Les deux
cron
travaux sont exécutés en fait chaque minute mais celui- ci on va attendre une demi - minute avant d' exécuter la « viande » du travail,/path/to/executable
.Pour d'autres
cron
options (non basées), voir les autres réponses ici, en particulier celles mentionnantfcron
etsystemd
. Celles-ci sont probablement préférables en supposant que votre système a la capacité de les utiliser (comme installerfcron
ou avoir une distribution avecsystemd
).Si vous ne souhaitez pas utiliser la solution kludgy, vous pouvez utiliser une solution basée sur une boucle avec une petite modification. Vous devrez toujours gérer le maintien de votre processus sous une forme ou une autre, mais une fois trié, le script suivant devrait fonctionner:
L'astuce consiste à utiliser un
sleep 30
mais à le démarrer en arrière - plan avant l'exécution de votre charge utile. Ensuite, une fois la charge utile terminée, attendez que l'arrière-plansleep
se termine.Si la charge utile prend
n
quelques secondes (oùn <= 30
), l'attente après la charge utile sera alors de30 - n
quelques secondes. Si cela prend plus de 30 secondes, le cycle suivant sera retardé jusqu'à ce que la charge utile soit terminée, mais plus.Vous verrez que j'ai du code de débogage là-dedans pour commencer sur une limite d'une minute pour rendre la sortie initialement plus facile à suivre. J'augmente également progressivement la durée maximale de la charge utile afin que vous finissiez par voir la charge utile dépasser le temps de cycle de 30 secondes (une ligne vierge supplémentaire est sortie, l'effet est donc évident).
Un cycle d'échantillonnage suit (où les cycles commencent normalement 30 secondes après le cycle précédent):
Si vous voulez éviter la solution kludgy, c'est probablement mieux. Vous aurez toujours besoin d'un
cron
travail (ou équivalent) pour détecter périodiquement si ce script est en cours d'exécution et, sinon, le démarrer. Mais le script lui-même gère alors le timing.(a) Certains de mes collègues diraient que les gourmandises sont ma spécialité :-)
la source
Tu ne peux pas. Cron a une granularité de 60 secondes.
la source
&&
au lieu de( ; )
.&&
opérateur court-circuite, donc la commande suivante dans la chaîne n'est pas exécutée si la précédente a échoué.La granularité de Cron est en quelques minutes et n'a pas été conçue pour se réveiller toutes les
x
secondes pour exécuter quelque chose. Exécutez votre tâche répétitive dans une boucle et elle devrait faire ce dont vous avez besoin:la source
while [ true ]
raison pour laquelle vous avez beaucoup d'instances du même script, car cron en lancera un nouveau toutes les minutes?sleep $remainingTime
où le temps restant est de 30 moins le temps pris par le travail (et le plafonner à zéro s'il a pris> 30 secondes). Vous prenez donc le temps avant et après le travail réel et calculez la différence.Si vous utilisez un système d'exploitation Linux récent avec SystemD, vous pouvez utiliser l'unité SystemD Timer pour exécuter votre script à n'importe quel niveau de granularité que vous souhaitez (théoriquement jusqu'à nanosecondes), et - si vous le souhaitez - des règles de lancement beaucoup plus flexibles que Cron n'a jamais autorisé . Aucun
sleep
kludges requisIl faut un peu plus de temps pour configurer qu'une seule ligne dans un fichier cron, mais si vous avez besoin de quelque chose de mieux que "Chaque minute", cela vaut bien l'effort.
Le modèle de temporisation SystemD est essentiellement le suivant: les temporisateurs sont des unités qui démarrent des unités de service lorsqu'une temporisation s'est écoulée .
Donc, pour chaque script / commande que vous souhaitez planifier, vous devez avoir une unité de service, puis une unité de temporisation supplémentaire. Une seule unité de minuterie peut inclure plusieurs planifications, vous n'avez donc normalement pas besoin de plus d'une minuterie et d'un service.
Voici un exemple simple qui enregistre "Hello World" toutes les 10 secondes:
/etc/systemd/system/helloworld.service
:/etc/systemd/system/helloworld.timer
:Après avoir configuré ces unités (dans
/etc/systemd/system
, comme décrit ci-dessus, pour un paramètre à l'échelle du système ou~/.config/systemd/user
pour une configuration spécifique à l'utilisateur), vous devez activer la minuterie (mais pas le service) en exécutantsystemctl enable --now helloworld.timer
(l'--now
indicateur démarre également la minuterie immédiatement, sinon, il ne démarrera qu'après le prochain démarrage ou la connexion de l'utilisateur).Les
[Timer]
champs de section utilisés ici sont les suivants:OnBootSec
- démarrez le service autant de secondes après chaque démarrage.OnUnitActiveSec
- démarrez le service autant de secondes après le dernier démarrage du service. C'est ce qui fait que la minuterie se répète et se comporte comme une tâche cron.AccuracySec
- définit la précision de la minuterie. Les minuteries ne sont aussi précises que ce champ définit, et la valeur par défaut est 1 minute (émule cron). La principale raison pour ne pas exiger la meilleure précision est d'améliorer la consommation d'énergie - si SystemD peut planifier la prochaine exécution pour coïncider avec d'autres événements, il doit réveiller le processeur moins souvent. L'1ms
exemple ci-dessus n'est pas idéal - je règle généralement la précision sur1
(1 seconde) dans mes tâches planifiées d'une minute, mais cela signifierait que si vous regardez le journal affichant les messages "Hello World", vous verriez que il est souvent en retard d'une seconde. Si vous êtes d'accord avec cela, je suggère de définir la précision sur 1 seconde ou plus.Comme vous l'avez peut-être remarqué, cette minuterie n'imite pas très bien Cron - dans le sens où la commande ne démarre pas au début de chaque période d'horloge murale (c'est-à-dire qu'elle ne démarre pas à la 10e seconde de l'horloge, puis le 20 et ainsi de suite). Au lieu de cela, cela se produit uniquement lorsque la minuterie s'écoule. Si le système démarre à 12:05:37, la prochaine exécution de la commande sera alors à 12:05:47, puis à 12:05:57, etc. Si vous êtes intéressé par la précision réelle de l'horloge murale, alors vous pouvez pour remplacer les
OnBootSec
et lesOnUnitActiveSec
champs et au lieu définir uneOnCalendar
règle avec le calendrier que vous voulez (qui, autant que je sache ne peut pas être plus rapide de 1 seconde, en utilisant le format de calendrier). L'exemple ci-dessus peut également s'écrire:Dernière remarque: comme vous l'avez probablement deviné, l'
helloworld.timer
unité démarre l'helloworld.service
unité car elle porte le même nom (moins le suffixe du type d'unité). Il s'agit de la valeur par défaut, mais vous pouvez la remplacer en définissant leUnit
champ de la[Timer]
section.Plus de détails sanglants peuvent être trouvés sur:
man systemd.timer
man systemd.time
man systemd.service
man system.exec
la source
Pas besoin de deux entrées cron, vous pouvez les mettre en une avec:
donc dans votre cas:
* * * * * /bin/bash -l -c "cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'' ; sleep 30 ; cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''"
la source
Vous pouvez consulter ma réponse à cette question similaire
Fondamentalement, j'ai inclus un script bash nommé "runEvery.sh" que vous pouvez exécuter avec cron toutes les 1 minute et passer en arguments la vraie commande que vous souhaitez exécuter et la fréquence en secondes pendant laquelle vous souhaitez l'exécuter.
quelque chose comme ça
* * * * * ~/bin/runEvery.sh 5 myScript.sh
la source
Utilisez la montre:
la source
$ watch --interval .10 php some_file.php
? ouwatch
fonctionne uniquement avec des fichiers .sh?--interval .30
ne s'exécutera donc pas deux fois par minute. C'est-à-direwatch -n 2 "sleep 1 && date +%s"
qu'il augmentera toutes les 3 secondes.watch
été conçu pour être utilisé par un terminal, donc - bien qu'il puisse fonctionner sans terminal (exécuté avecnohup
puis se déconnecter) ou avec un faux terminal (tel quescreen
) - il n'a pas les moyens de se comporter comme un cron, comme la récupération après une panne, redémarrage après le démarrage, etc '.Le travail Cron ne peut pas être utilisé pour planifier un travail en quelques secondes. c'est-à-dire que vous ne pouvez pas planifier une tâche cron pour qu'elle s'exécute toutes les 5 secondes. L'alternative est d'écrire un script shell qui utilise une
sleep 5
commande dedans.Créez un script shell toutes les 5 à 5 secondes à l'aide de la boucle bash while, comme illustré ci-dessous.
Maintenant, exécutez ce script shell en arrière-plan en utilisant
nohup
comme indiqué ci-dessous. Cela continuera à exécuter le script même après la déconnexion de votre session. Cela exécutera votre script shell backup.sh toutes les 5 secondes.la source
backup.sh
exécution prend 1,5 seconde, il s'exécutera toutes les 6,5 secondes. Il y a des façons d'éviter cela, par exemplesleep $((5 - $(date +%s) % 5))
Utilisez fcron ( http://fcron.free.fr/ ) - vous donne une granularité en quelques secondes et bien meilleure et plus riche en fonctionnalités que cron (vixie-cron) et stable aussi. J'avais l'habitude de faire des choses stupides comme avoir environ 60 scripts PHP en cours d'exécution sur une machine dans des paramètres très stupides et il a toujours fait son travail!
la source
en dir
/etc/cron.d/
nouveau créer un fichier
excute_per_30s
exécutera cron toutes les 30 secondes
la source
Actuellement, j'utilise la méthode ci-dessous. Fonctionne sans problème.
Si vous voulez exécuter toutes les N secondes alors X aura 60 / N et Y sera N .
Je vous remercie.
la source
YOUR_COMMANDS
àYOUR_COMMANDS &
, afin que la commande soit lancée en arrière-plan, sinon, si la commande prend plus d'une fraction de seconde - cela retardera le prochain lancement. Donc avec X = 2 et Y = 30, si la commande prend 10 secondes - elle se lancera à la minute puis 40 secondes plus tard, au lieu de 30. Bravo à @paxdiablo./bin/bash -c
partie (y compris les guillemets d'argument), le script ne s'exécute que toutes les minutes, en ignorant l'itération (dans mon casX=12
etY=5
).Le travail Crontab peut être utilisé pour planifier un travail en minutes / heures / jours, mais pas en quelques secondes. L'alternative :
Créez un script à exécuter toutes les 30 secondes:
Utilisez
crontab -e
et une crontab pour exécuter ce script:la source
Vous pouvez exécuter ce script en tant que service, redémarrer toutes les 30 secondes
Enregistrer un service
Collez la commande ci-dessous
Services de rechargement
Activer le service
Démarrez le service
Vérifiez l'état de votre service
la source
Merci pour toutes les bonnes réponses. Pour faire simple, j'ai aimé la solution mixte, avec le contrôle sur crontab et la division temporelle sur le script. C'est donc ce que j'ai fait pour exécuter un script toutes les 20 secondes (trois fois par minute). Ligne Crontab:
Scénario:
la source
écrire un script shell créer un fichier .sh
nano every30second.sh
et écrire un script
puis définissez cron pour ce script crontab -e
(* * * * * /home/username/every30second.sh)
ce fichier .sh d'appel cron toutes les 1 min et dans la commande de fichier .sh est exécuté 2 fois en 1 min
si vous voulez exécuter le script pendant 5 secondes, remplacez 30 par 5 et changez pour la boucle comme ceci:
For (( i=1; i <= 12; i++ ))
lorsque vous sélectionnez une seconde, puis calculez 60 / votre seconde et écrivez dans la boucle For
la source
J'ai juste eu une tâche similaire à faire et à utiliser l'approche suivante:
J'avais besoin d'avoir un kill périodique -3 (pour obtenir la trace de la pile d'un programme) toutes les 30 secondes pendant plusieurs heures.
C'est là pour être sûr que je ne perds pas l'exécution de watch si je perds le shell (problème réseau, plantage de windows etc ...)
la source
Jetez un oeil à fréquent-cron - il est ancien mais très stable et vous pouvez descendre à la micro-seconde. À ce stade, la seule chose que je dirais contre, c'est que j'essaie toujours de savoir comment l'installer en dehors d'init.d mais en tant que service systemd natif, mais certainement jusqu'à Ubuntu 18, il ne fonctionne que très bien en utilisant init.d (la distance peut varier sur ces dernières versions). Il a l'avantage supplémentaire (?) De garantir qu'il ne générera pas une autre instance du script PHP à moins qu'une précédente ne soit terminée, ce qui réduit les problèmes potentiels de fuite de mémoire.
la source
Exécuter dans une boucle shell, exemple:
la source
60
devrait être un30
, vous voudrez peut-être le déplacerwget
à l' intérieur de l'if
instruction, sinon il est exécuté chaque seconde. En tout cas, je ne sais pas en quoi c'est mieux qu'un simplesleep 30
. Si vous surveilliez l'heure UNIX réelle plutôt que votre compteur, cela ferait une différence.