Cron job e tempi casuali, entro determinate ore


100

Ho bisogno della capacità di eseguire uno script PHP 20 volte al giorno in orari completamente casuali. Voglio anche che funzioni solo tra le 9:00 e le 23:00.

Ho familiarità con la creazione di cron job in Linux.


1
La domanda non è molto ben posta. In definitiva, vuoi distribuire 20 punti sull'asse del tempo tra le 9:00 e le 11:00. Ma ci sono vincoli alla differenza di tempo minima? È accettabile non fare nulla tra le 9:00 e le 10:30? L'unico modo per farlo sembra accettabile all'idea di Klaus: seleziona le tue 20 volte alle 09:00, che ti permette di soddisfare tutti i vincoli che potresti avere, quindi programma le cose con "alle".
David Tonhofer

Risposte:


38

Se capisco cosa stai cercando, dovrai fare qualcosa di un po 'disordinato, come avere un cron job che esegue uno script bash che randomizza i tempi di esecuzione ... Qualcosa del genere:

crontab:

0 9 * * * /path/to/bashscript

e in / 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

Alcune note: questo approccio è un po 'dispendioso di risorse, poiché alle 9 del mattino attiva 20 processi in background, ognuno dei quali attende un numero casuale di minuti (fino a 14 ore, ovvero le 23), quindi avvia lo script php e esce. Inoltre, poiché utilizza un numero casuale di minuti (non secondi), i tempi di inizio non sono così casuali come potrebbero essere. Ma $ RANDOM arriva solo a 32.767 e ci sono 50.400 secondi tra le 9:00 e le 23:00, sarebbe un po 'più complicato anche randomizzare i secondi. Infine, poiché gli orari di inizio sono casuali e indipendenti l'uno dall'altro, è possibile (ma non molto probabile) che due o più istanze dello script vengano avviate contemporaneamente.


2
È possibile rendere più leggibili le assegnazioni aritmetiche facendo cadere il segno del dollaro e spostando le doppie parentesi a sinistra (ad esempio ((maxdelay = 14 * 60))o ((delay = $RANDOM % maxdelay))). L' sleepargomento deve ancora essere il modo in cui lo hai (anche se potresti aggiungere spazi, se lo desideri).
In pausa fino a nuovo avviso.

Questo ha funzionato anche per me. Il mio script bash personalizzato ha il seguente aspetto sleep $[ ( $RANDOM % 60 ) + 1 ]s && some_script.sh
Shyam Habarakada

Mi manca qualcosa o il ritardo massimo dovrebbe essere impostato su maxdelay = $ ((14 *
60/20

@jenishSakhiya I ritardi casuali per ciascuna delle 20 corse sono assoluti (beh, a partire dalle 9:00), non relativi a un'altra delle corse. Cioè, se uno dei ritardi casuali arriva a 13 ore, significa che verrà eseguito alle 22:00 (13 ore dopo le 9:00), non 13 ore dopo le altre esecuzioni.
Gordon Davisson

138

Sì, sì, la domanda è vecchia di più di un anno, ma forse posso aggiungere qualcosa di utile:

Come cron qualcosa con un offset casuale 20 volte al giorno tra le 9:00 e le 23:00? Questo è un po 'complicato all'interno di cron, perché stai dividendo 14 ore per 20 tempi di esecuzione. Non mi piacciono molto le altre risposte perché richiedono la scrittura di uno script wrapper bash per il tuo script php.

Tuttavia, se mi permetti la libertà di allentare la limitazione dei tempi e della frequenza a 13 volte tra le 8:30 e le 23:09, questo potrebbe fare il trucco, e tutto entro i confini del tuo crontab:

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

$ {RANDOM: 3: 2} usa $ RANDOM di bash che altre persone hanno menzionato sopra, ma aggiunge lo slicing dell'array di bash. Poiché le variabili bash non sono tipizzate, il numero a 16 bit con segno pseudocasuale viene troncato alle prime 2 delle sue 5 cifre decimali, dandoti una breve riga per ritardare il tuo cronjob tra 10 e 99 minuti (sebbene la distribuzione sia polarizzata verso Da 10 a 32).

Quanto segue potrebbe funzionare anche per te, ma ho scoperto che è "meno casuale" per qualche motivo (forse la legge di Benford è attivata modulando numeri pseudo-casuali. Ehi, non lo so, ho bocciato la matematica ... su bash!):

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

Devi rendere il modulo come '\%' sopra perché cron (beh, almeno Linux 'vixie-cron') termina la riga quando incontra un '%' senza caratteri di escape.

Forse potresti ottenere le restanti 7 esecuzioni di script aggiungendo un'altra riga con un altro intervallo di 7 ore. Oppure allenta la tua restrizione per correre tra le 3:00 e le 23:00.


4
Mi piace la risposta in ritardo. Ma se stai cercando di generare un numero intero casuale distribuito uniformemente nell'intervallo da 10 a 99 e l'output di RANDOM è compreso tra 0 e 32.767, perché non dovresti farlo $[(RANDOM/368)+10]?
jsdalton

3
@jsdalton: l'operatore modulo non sarebbe migliore? $((RANDOM % 90 + 10))Test:for i in {0..9999}; do echo $((RANDOM % 90 + 10)); done | sort | uniq -c
geon

5
Su molti sistemi cron non usa bash di default quindi potrebbe essere meglio evitare il da bash $RANDOM: sleep $(( $(od -N1 -tuC -An /dev/urandom) \% 90 ))m.
pabouk

9
Assicurati che crontabstia usando bashprima di usare $RANDOM. Se lo hai vixie-cron(sembra essere il mio caso su Ubuntu), puoi aggiungere SHELL=/bin/bashin cima. Ci sono più alternative per altre versioni di cron qui: superuser.com/a/264541/260350
DaAwesomeP

1
Quando uso il primo suggerimento sopra, ottengo crontab: errors in crontab file, can't install. Do you want to retry the same edit?aiuto per favore
Seano

72

Quindi sto usando quanto segue per eseguire un comando tra 1AM e 330AM

0 1 * * * perl -le 'sleep rand 9000' && *command goes here*

Questo si è preso cura dei miei bisogni casuali per me. Sono 9000 secondi == 150 minuti == 2,5 ore


8
:: MindBLOWN :: un altro posto oscuro dove usare un po 'di perl.
Mark Carpenter Jr

Questa è sicuramente la risposta più pulita
Enrico Detoma

Tuttavia, questo è un po 'inefficiente, poiché stai creando molti processi.
kahveciderin

21

Cron offre una RANDOM_DELAYvariabile. Vedere crontab(5)per i dettagli.

La variabile RANDOM_DELAY consente di ritardare gli avvii del lavoro di una quantità casuale di minuti con il limite superiore specificato dalla variabile.

Questo è visto comunemente nei anacronlavori, ma può anche essere utile in un file crontab.

Potrebbe essere necessario fare attenzione con questo se alcuni lavori vengono eseguiti con granularità fine (minuto) e altri che sono grossolani.


Mi piacerebbe usare la variabile RANDOM_DELAY, ma non riesco a trovare alcun suggerimento nella manpage di crontab (5) su Ubuntu 14.04.4 LTS.
Exocom

È un peccato. Mi chiedo se non sia supportato lì. Lo vedo documentato in quella manpage su Centos 7 e Arch Linux.
Micah Elliott

9
questa sembra la risposta corretta ma puoi fare un esempio?
chovy

14
Notare che RANDOM_DELAYviene stabilito una volta e rimane costante per l'intero runtime del daemon.
Maciej Swic

5
Il RANDOM_DELAYflag è una caratteristica di cronie-crond mentre sembra essere in esecuzione Ubuntu vixie-cronche manca di questo flag.
kravietz

7

Il mio primo pensiero sarebbe stato quello di creare un cron job avviando 20 programmati casualmente nei job. L' atutilità (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) viene utilizzata per eseguire i comandi all'ora specificata.


Un esempio di utilizzo di è qui: stackoverflow.com/a/6136145/803174
Kangur

6

Ho finito per usare sleep $(( 1$(date +%N) % 60 )) ; dostuffs(compatibile con bash & sh)

Il prefisso 1 serve a forzare l'interpretazione NON in base 8 della data +% N (es. 00551454)

Non dimenticare di uscire da% usando \% in un file crontab

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

2
Se qualcuno si chiede, come me:% N fornisce gli attuali nano, ma alcune pagine di manuale mancano di informazioni. Questa è una soluzione molto intelligente per le persone che hanno bisogno di "un po 'di casualità" facilmente per comando.
Thorsten Schöning

A parte gli avvertimenti già trattati altrove, questo funzionerà solo se hai GNU date(cosa che probabilmente fai sulla maggior parte dei Linux, ma non su Busybox, MacOS standard o varie altre piattaforme derivate da BSD).
tripleee

4

La soluzione di al-x non funziona per me poiché i comandi crontab non vengono eseguiti in bash ma in sh immagino. Quello che funziona è:

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

Ho provato di tutto e ancora non ha funzionato per me. Hai spiegato perché, grazie!
Marlar

$[ ... ]è una sintassi deprecata da molto tempo; per qualsiasi cosa di questo millennio, preferiresti $((RANDOM\%90))mquale sintassi compatibile con POSIX (ma ovviamente RANDOMè ancora solo Bash).
tripleee

1

at -f [file] [timespec]

o

echo [command] | at [timespec]

o

at [timespec]... e specifiche interattive come scriptla registrazione di.

Comando

All'esecuzione il testo fornisce su stdin o nel file specificato da -f [file].

Timespec

Ecco la [timespec] grammatica . Può essere qualcosa come:

  • 24 ore di tempo come int 4 cifre, ad esempio 0100, 2359,1620
  • now + 10 minutes
  • 2071-05-31 - 5 hours 12 minutes UTC

Se stai specificando esplicitamente il fuso orario, alcune versioni di timespec potrebbero consentire solo UTCl'argomento facoltativo timezone.

Esempio

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

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

Provalo...

Puoi testare l'analisi bash anticipando echoed eseguendo l'escape della |(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

Per visualizzare i lavori pianificati, utilizzare atqe il contenuto del lavoro (variabili di ambiente, configurazione e comando / script) con at -c [jobid].

Nota

Il sistema fa parte di cron e il prompt interattivo acquisisce effettivamente l'intero stato corrente della shell, quindi è possibile eseguire comandi senza specificare percorsi assoluti.


0

Per coloro che hanno cercato su Google la strada qui:

Se stai usando anacron (desktop e laptop Ubuntu), puoi modificare

/etc/anacrontab

e aggiungi

RANDOM_DELAY=XX 

Dove XX è la quantità di minuti che si desidera ritardare il lavoro di base.

Anacron è come cron, ma non si aspetta che il tuo computer sia attivo 24 ore su 24, 7 giorni su 7 (come i nostri laptop) ed eseguirà gli script che ha perso perché il sistema era inattivo.


0

Puoi provare con questo esempio a utilizzare tempi casuali prima di eseguire il comando:

#!/bin/bash
# start time
date +"%H:%M:%S"

# sleep for 5 seconds
sleep $(shuf -i 1-25 -n 1)
# end time
date +"%H:%M:%S"

0

Che ne dici di creare uno script che riscrive il crontab ogni giorno?

  1. Leggi i cron attuali (A)
  2. Scegli orari casuali (B)
  3. Riscrivi i cron precedenti (A), aggiungi nuovi cron casuali (B)
  4. Assicurati di aggiungere al cron per eseguire questo script in primo luogo.

2
Non aggirare il sistema di reputazione pubblicando commenti come risposte. Il tuo commento sembra comunque abbastanza buono da essere effettivamente una risposta. Consiglio di rimuovere " Non ho un rappresentante per aggiungere un commento, ma ".
Ted Lyngmo

1
Ho appena rivisto questa risposta e ho perso la parte in cui stai facendo una domanda in cambio alla fine (lavoro sciatto da parte mia). Non fare domande nelle risposte. Pubblica la tua domanda per le domande che hai. Ho trasformato la tua semi-domanda in qualcosa che potrebbe passare per una risposta.
Ted Lyngmo

1
Fatto! Grazie. La prossima volta starò più attento, non intendevano cattive intenzioni.
mellofellow il

1
Sono sicuro che non hai avuto cattive intenzioni e non devi essere eccessivamente attento. Hai delineato una possibile soluzione e alla fine sei inciampato. Nessun problema!
Ted Lyngmo

0

Mi rendo conto che è un thread più vecchio, ma voglio aggiungere una cosa correlata a valori casuali che uso molto. Invece di utilizzare la variabile $ RANDOM con un intervallo fisso e limitato, spesso creo valori casuali di intervallo arbitrario nella shell con

dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -N4 -t u4 -A none

così puoi fare, ad esempio,

FULLRANDOM=$(dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -N4 -t u4 -A none)

e superare alcune delle restrizioni discusse in questo thread.


1
Benvenuto in SO. Bene, vecchio thread o no, questo mi ha mandato a ~$info dde posso capire cosa sta succedendo sul lato sinistro di |, ma non riesco a distinguere il lato destro. Quindi, per me e gli altri interessati alla overcoming some restrictionsgenerazione di valori casuali, perché non dedicare un momento a spiegare l'RHS e fare un passo più forte per utilizzare il tuo approccio. La profondità della spiegazione mette le persone a proprio agio con il processo che suggerisci e con i suoi vantaggi. Grazie.
Chris

Ah ok. od aka "ottale dump" prende un file o stdin e scarica i dati binari in forma leggibile dall'uomo. Vogliamo che il nostro numero venga mostrato come un decimale senza segno (-t u4) e non vogliamo che l'indice dell'indirizzo (-A nessuno). -N4 è ridondante poiché prendiamo solo 4 byte, ma non fa male neanche. Spero che questo lo spieghi ...
MLP
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.