web-dev-qa-db-fra.com

Lancer un cron toutes les 30 secondes

Ok, donc j'ai 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'\'''

Ça fonctionne, mais est-ce que ça marche toutes les 30 minutes ou toutes les 30 minutes? 

De plus, j'ai lu que cron n'était peut-être pas le meilleur outil à utiliser si je le lance souvent. Y at-il un autre meilleur outil que je peux utiliser ou installer sur Ubuntu 11.04 qui sera une meilleure option? Y at-il un moyen de réparer le cron ci-dessus?

221
Matt Elhotiby

Vous avez */30 dans le spécificateur minutes - cela signifie toutes les minutes, mais par pas de 30 (autrement dit, toutes les demi-heures). Puisque cron ne descend pas aux résolutions inférieures à une minute, vous devrez trouver un autre moyen.

Une possibilité, bien que ce soit un peu maladroit, est d’avoir deux tâches, une décalée de 30 secondes:

* * * * * /path/to/executable param1 param2
* * * * * ( sleep 30 ; /path/to/executable param1 param2 )

Les deux travaux cron sont exécutés toutes les minutes, mais ce dernier attend une demi-minute avant d'exécuter la "viande" du travail, /path/to/executable.

580
paxdiablo

Tu ne peux pas. Cron a une granularité de 60 secondes.

* * * * * 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'\''
53
wildplasser

La granularité de Cron est exprimée en minutes et n'était pas 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 il devrait faire ce dont vous avez besoin:

#!/bin/env bash
while [ true ]; do
 sleep 30
 # do what you need to here
done
35
Marvin Pinto

Pas besoin de deux entrées cron, vous pouvez la mettre en une avec:

* * * * * /bin/bash -l -c "/path/to/executable; sleep 30 ; /path/to/executable"

alors 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'\''"

22
Andrew

Vous pouvez consulter ma réponse à cette question similaire

En gros, j’ai inclus un script bash nommé "runEvery.sh" que vous pouvez exécuter avec cron toutes les minutes et transmettre en tant qu’arguments la vraie commande à exécuter et la fréquence en secondes à laquelle vous souhaitez l’exécuter.

quelque chose comme ça

* * * * * ~/bin/runEvery.sh 5 myScript.sh

11
shlomia

Le travail périodique ne peut pas être utilisé pour planifier un travail en secondes. En d'autres termes, vous ne pouvez pas planifier l'exécution d'un travail cron toutes les 5 secondes. L'alternative consiste à écrire un script Shell qui utilise la commande sleep 5.

Créez un script shell toutes les 5 secondes en utilisant bash en boucle, comme indiqué ci-dessous.

$ cat every-5-seconds.sh
#!/bin/bash
while true
do
 /home/ramesh/backup.sh
 sleep 5
done

Exécutez maintenant ce script Shell en arrière-plan en utilisant Nohup comme indiqué ci-dessous. Cela continuera à exécuter le script même après vous être déconnecté de votre session. Ceci exécutera votre script shell backup.sh toutes les 5 secondes.

$ Nohup ./every-5-seconds.sh &
9
Pankaj Shinde

Utilisez la montre:

$ watch --interval .30 script_to_run_every_30_sec.sh
7
user7079817

dans dir /etc/cron.d/

new créer un fichier excute_per_30s

* * * * * yourusername  /bin/date >> /home/yourusername/temp/date.txt
* * * * * yourusername sleep 30; /bin/date >> /home/yourusername/temp/date.txt

exécutera cron toutes les 30 secondes

6
LingYFH

Utilisez fcron ( http://fcron.free.fr/ ) - vous donne une granularité en quelques secondes et une qualité bien meilleure et plus riche en fonctionnalités que cron (vixie-cron) et stable. J'avais l'habitude de faire des choses stupides, comme avoir environ 60 scripts php en cours d'exécution sur une seule machine dans des paramètres très stupides, et cela fonctionnait toujours!

5
Adi Chiru

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é souhaité (théoriquement jusqu'à une nanoseconde) et, si vous le souhaitez, des règles de lancement beaucoup plus souples que celles autorisées par Cron. . Non sleep kludges required

Il faut un peu plus de temps pour mettre en place qu'une seule ligne dans un fichier cron, mais si vous avez besoin de quelque chose de mieux que "Every minute", cela en vaut vraiment la peine.

Le modèle de minuterie SystemD est essentiellement le suivant: _ les temporisateurs sont des unités qui démarrent des unités de service lorsqu'un délai est écoulé.

Ainsi, pour chaque script/commande que vous souhaitez planifier, vous devez disposer d'une unité de service, puis d'une unité de minuterie supplémentaire. Une seule minuterie peut inclure plusieurs programmes, vous n’auriez 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:

[Unit]
Description=Say Hello
[Service]
ExecStart=/usr/bin/logger -i Hello World

/etc/systemd/system/helloworld.timer:

[Unit]
Description=Say Hello every 10 seconds
[Timer]
OnBootSec=10
OnUnitActiveSec=10
AccuracySec=1ms
[Install]
WantedBy=timers.target

Après avoir configuré ces unités (dans /etc/systemd/system, comme décrit ci-dessus, pour un réglage global, ou à ~/.config/systemd/user pour une configuration spécifique à l'utilisateur), vous devez activer le minuteur (pas le service cependant) en exécutant systemctl enable helloworld.timer. Si vous souhaitez démarrer le minuteur immédiatement (au lieu d'attendre qu'il redémarre après un redémarrage), exécutez également systemctl start helloworld.timer.

Les champs de la section [Timer] utilisés ici sont les suivants:

  • OnBootSec - démarrez le service plusieurs secondes après chaque démarrage.
  • OnUnitActiveSec - démarrez le service plusieurs secondes après le dernier démarrage du service. C'est ce qui fait que le minuteur se répète et se comporte comme un travail cron.
  • AccuracySec - définit la précision du chronomètre. Les minuteurs sont aussi précis que ce champ est défini 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 moins souvent le processeur. Le 1ms dans l'exemple ci-dessus n'est pas idéal. Je règle généralement l'exactitude sur 1 (1 seconde) dans les tâches planifiées d'une minute, mais cela voudrait dire que si vous consultez le journal qui affiche les messages "Hello World", voyez qu'il est souvent en retard d'une seconde. Si cela vous convient, je suggère de régler la précision à 1 seconde ou plus.

Comme vous l'avez peut-être remarqué, cette minuterie n'imite pas très bien Cron - en ce sens que la commande ne commence pas au début de chaque période d'horloge murale (c'est-à-dire qu'elle ne commence pas à la 10e seconde de l'horloge, puis le 20 et ainsi de suite). Au lieu de cela est juste arrive lorsque le ellapses minuterie. Si le système a démarré à 12:05:37, la commande suivante sera exécutée à 12:05:47, puis à 12:05:57, etc. Si la précision de l'horloge murale vous intéresse, vous pouvez voulez remplacer les champs OnBootSec et OnUnitActiveSec et définir à la place une règle OnCalendar avec la planification souhaitée (qui, autant que je sache, ne peut pas être plus rapide que 1 seconde, en utilisant le format de calendrier). L'exemple ci-dessus peut également être écrit comme suit:

OnCalendar=*-*-* *:*:00,10,20,30,40,50

Dernière remarque: comme vous l'avez probablement deviné, l'unité helloworld.timer démarre l'unité helloworld.service car elle porte le même nom (moins le suffixe de type d'unité). C'est la valeur par défaut, mais vous pouvez le remplacer en définissant le champ Unit pour la section [Timer].

Plus de détails sanglants peuvent être trouvés à:

4
Guss

Le travail Crontab peut être utilisé pour planifier un travail en minutes/heures/jours, mais pas en secondes. L'alternative :

Créez un script à exécuter toutes les 30 secondes:

#!/bin/bash
# 30sec.sh

for COUNT in `seq 29` ; do
  cp /application/tmp/* /home/test
  sleep 30
done

Utilisez crontab -e et une crontab pour exécuter ce script:

* * * * * /home/test/30sec.sh > /dev/null
4
szaier

Merci pour toutes les bonnes réponses. Pour simplifier les choses, 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: 

 * * * * 1-6 ./a/b/checkAgendaScript >> /home/a/b/cronlogs/checkAgenda.log

Scénario: 

cd /home/a/b/checkAgenda

Java -jar checkAgenda.jar
sleep 20
Java -jar checkAgenda.jar 
sleep 20
Java -jar checkAgenda.jar 
1
jfajunior

Jetez un oeil à fréquentes-cron - il est vieux mais très stable et vous pouvez passer à 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 de init.d mais en tant que service systemd natif, mais certainement jusqu’à Ubuntu 18, il ne fonctionne que bien en utilisant toujours init.d (la distance peut varier sur les dernières versions). Il présente l’avantage supplémentaire (?) De s’assurer qu’il ne créera pas d’autre instance du script PHP à moins qu’une autre ne soit terminée, ce qui réduit les problèmes de fuites de mémoire.

0
bnoeafk

Je viens d'avoir une tâche similaire à faire et utiliser l'approche suivante: 

Nohup watch -n30 "kill -3 NODE_PID" &

Je devais avoir un kill périodique -3 (pour obtenir la trace de la pile d'un programme) toutes les 30 secondes pendant plusieurs heures.

Nohup ... & 

Ceci est ici pour être sûr que je ne perds pas l'exécution de watch si je perds le Shell (problème de réseau, plantage de Windows, etc ...)

0
Thomas

écrire un script Shell créer un fichier .sh

nano every30second.sh

et écrire le script

#!/bin/bash
For  (( i=1; i <= 2; i++ ))
do
    write Command here
    sleep 30
done

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 remplacez la boucle comme suit: For (( i=1; i <= 12; i++ ))

lorsque vous sélectionnez une seconde, calculez 60/votre seconde et écrivez dans la boucle For

0
Aditya Gosavi

Actuellement, j'utilise la méthode ci-dessous. Fonctionne sans problèmes.

* * * * * /bin/bash -c ' for i in {1..X}; do YOUR_COMMANDS ; sleep Y ; done '

Si vous voulez exécuter toutes les N secondes, X sera 60/N et Y sera N.

Je vous remercie.

0
sujoshi