web-dev-qa-db-fra.com

Tâches Cron et heures aléatoires, dans des heures données

J'ai besoin de la capacité d'exécuter un script PHP 20 fois par jour à des heures complètement aléatoires. Je souhaite également qu'il s'exécute uniquement entre 9h et 23h.

Je suis habitué à créer des tâches cron sous linux.

84
floatleft

Si je comprends ce que vous recherchez, vous devrez faire quelque chose de désordonné, comme avoir un travail cron qui exécute un script bash qui randomise les temps d'exécution ... Quelque chose comme ça:

crontab:

0 9 * * * /path/to/bashscript

et dans/path/to/bashscript:

#!/bin/bash

maxdelay=$((14*60))  # 14 hours from 9am to 11pm, converted to minutes
for ((i=1; i<=20; i++)); do
    delay=$(($RANDOM%maxdelay)) # pick an independent random delay for each of the 20 runs
    (sleep $((delay*60)); /path/to/phpscript.php) & # background a subshell to wait, then run the php script
done

Quelques notes: cette approche gaspille un peu en ressources, car elle déclenche 20 processus en tâche de fond à 9h du matin, chacun attendant un nombre aléatoire de minutes (jusqu’à 14 heures, soit 23h), puis lance le script php et sorties. De plus, comme il utilise un nombre aléatoire de minutes (et non de secondes), les heures de début ne sont pas aussi aléatoires qu'elles pourraient l'être. Mais $ RANDOM ne monte que jusqu'à 32 767, et il y a 50 400 secondes entre 9h et 23h, ce serait un peu plus compliqué de randomiser les secondes également. Enfin, comme les heures de début sont aléatoires et indépendantes les unes des autres, il est possible (mais pas très probable) que deux instances ou plus du script soient démarrées simultanément.

30
Gordon Davisson

Ouais, oui, la question a plus d'un an, mais je peux peut-être ajouter quelque chose d'utile:

Comment faire quelque chose avec un décalage aléatoire 20 fois par jour entre 9h et 23h? C'est un peu délicat avec cron, car vous divisez 14 heures par 20 fois le temps d'exécution. Je n'aime pas beaucoup les autres réponses car elles nécessitent l'écriture d'un script wrapper bash pour votre script php.

Cependant, si vous me permettez la liberté de réduire à 13 fois la restriction de fréquence et de fréquence entre 8h30 et 23h09, cela pourrait faire l'affaire, et tout cela dans les limites de votre crontab:

30 8-21/* * * * sleep ${RANDOM:0:2}m ; /path/to/script.php

$ {RANDOM: 3: 2} utilise le $ RANDOM de bash mentionné par d'autres personnes ci-dessus, mais ajoute le découpage en tableau de bash. Comme les variables bash ne sont pas typées, le nombre de 16 bits signé pseudo-aléatoire est tronqué aux 2 premiers de ses 5 chiffres décimaux, ce qui vous donne une ligne succincte pour retarder votre cronjob entre 10 et 99 minutes (bien que la distribution soit biaisée vers 10 à 32).

Ce qui suit pourrait également fonctionner pour vous, mais j’ai trouvé qu’il était "moins aléatoire" pour une raison quelconque (peut-être que la loi de Benford est déclenchée par la modulation de nombres pseudo-aléatoires. Hé, je ne sais pas, j’ai raté le calcul ... Blame it sur bash!):

30 8-21/* * * * sleep $[RANDOM\%90]m ; /path/to/script.php

Vous devez rendre le module sous la forme '\%' ci-dessus, car cron (enfin, au moins Linux 'vixie-cron') termine la ligne lorsqu'il rencontre un '%' non échappé.

Vous pourriez peut-être inclure les 7 exécutions de script restantes en ajoutant une autre ligne avec une autre plage de 7 heures. Ou relâchez votre restriction pour courir entre 3h et 23h.

119
al-x

J'utilise donc ce qui suit pour exécuter une commande entre 1h et 330h

0 1 * * * Perl -le 'sleep Rand 9000' && *command goes here*

Cela a pris soin de mes besoins aléatoires pour moi. C'est 9000 secondes == 150 minutes == 2,5 heures

53
Dave

Cron propose une variable RANDOM_DELAY. Voir crontab(5) pour plus de détails.

La variable RANDOM_DELAY permet de retarder le démarrage des travaux d'une quantité aléatoire de minutes avec une limite supérieure spécifiée par la variable.

Cela se voit couramment dans les travaux anacron, mais peut également être utile dans un fichier crontab.

Vous devrez peut-être faire attention à cela si vous avez des tâches qui fonctionnent à la fine granularité (minute) et d'autres qui sont grossières.

17
Micah Elliott

Ma première pensée a été de créer un travail cron en lançant 20 tâches planifiées de manière aléatoire. L'utilitaire at (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) est utilisé pour l'exécution de commandes à une heure spécifiée.

6
klaus

J'ai fini par utiliser sleep $(( 1$(date +%N) % 60 )) ; dostuffs (compatible avec bash & sh)

Le préfixe 1 consiste à forcer l’interprétation de la date +% N par la base NON 8 (par exemple, 00551454).

N'oubliez pas d'échapper à% en utilisant \% dans un fichier crontab

* * * * *  nobody  sleep $(( 1$(date +\%N) \% 60 )) ; dostuffs 
5
131

at -f [file] [timespec]

ou

echo [command] | at [timespec]

ou

at [timespec] ... et une spécification interactive comme l'enregistrement de script.

Commander

At exécute le texte à fournir sur stdin ou dans le fichier spécifié par -f [file].

Timespec

Voici la [timespec] Grammaire . Cela peut être quelque chose comme:

  • Heure sur 24 heures en tant qu'intérieur à 4 chiffres, par ex. 0100, 2359, 1620
  • now + 10 minutes
  • 2071-05-31 - 5 hours 12 minutes UTC

Si vous spécifiez explicitement le fuseau horaire, certaines versions de la durée spécifiée peut n'autoriser que UTC pour l'argument facultatif timezone.

Exemple

cat script.sh | at now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes

at -f script.sh now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes

Essaye le...

Vous pouvez tester l'analyse bash en mettant en attente echo et en évitant le | (Pipe).

echo cat script.sh \| at now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes

echo at -f script.sh now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes

Pour voir les tâches planifiées, utilisez atq et le contenu de la tâche (variables d'environnement, configuration et commande/script) avec at -c [jobid].

Remarque

Le système fait partie de cron et l'invite interactive capture en réalité tout l'état actuel de votre shell. Vous pouvez donc exécuter des commandes sans spécifier de chemins absolus.

1
mcint

la solution d'al-x ne fonctionne pas pour moi car les commandes crontab ne sont pas exécutées dans bash mais dans sh je suppose. Qu'est-ce que le travail est:

30 8 * * * bash -c "sleep $[RANDOM\%90]m" ; /path/to/script.py
0
Wilbert

Pour ceux qui googlé le chemin ici:

Si vous utilisez anacron (ordinateur de bureau et ordinateur portable Ubuntu), vous pouvez modifier

/etc/anacrontab

et ajouter

RANDOM_DELAY=XX 

Où XX correspond au nombre de minutes pendant lesquelles vous souhaitez différer le travail de base.

Anacron est comme cron mais il ne s'attend pas à ce que votre ordinateur soit sous 24x7 (comme nos ordinateurs portables) et exécutera les scripts qu'il a manqués car le système était en panne.

0
Ganesh Krishnan