Cron işleri ve verilen saatler içinde rastgele zamanlar


103

Tamamen rastgele zamanlarda bir PHP betiğini günde 20 kez çalıştırma yeteneğine ihtiyacım var. Ayrıca sadece 09:00 - 23:00 arasında çalışmasını istiyorum.

Linux'ta cron işleri oluşturmaya aşinayım.


1
Soru çok iyi sorulmamış. Nihayetinde, zaman eksenindeki 20 noktayı 09:00 ile 11:00 arasında dağıtmak istiyorsunuz. Ancak minimum zaman farkında kısıtlamalar var mı? 09:00 ve 10:30 arasında hiçbir şey yapmamak kabul edilebilir mi? Bunu kabul edilebilir bir şekilde yapmanın tek yolu Klaus'un fikrine görünüyor: 20 kez saatinizi 09: 00'da seçin; bu, sahip olabileceğiniz tüm kısıtlamaları yerine getirmenize ve ardından işleri "at" ile planlamanıza olanak tanır.
David Tonhofer

Yanıtlar:


39

Ne aradığınızı anlarsam, çalışma sürelerini rastgele hale getiren bir bash betiği çalıştıran bir cron işi gibi biraz dağınık bir şey yapmanız gerekecek ... Bunun gibi bir şey:

crontab:

0 9 * * * /path/to/bashscript

ve / bashscript'e / yolunda:

#!/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

Birkaç not: bu yaklaşım, her biri rastgele birkaç dakika (14 saate kadar, yani 23: 00'a kadar) boyunca bekleyen (14 saate kadar, yani 11: 00'a kadar) saat 9'da 20 arka plan işlemini başlattığı için biraz kaynak israfına neden olur ve ardından php betiğini başlatır ve çıkışlar. Ayrıca, rastgele bir dakika sayısı (saniye değil) kullandığı için, başlangıç ​​zamanları olabildiğince rastgele değildir. Ancak $ RANDOM yalnızca 32.767'ye kadar çıkıyor ve sabah 9 ile akşam 11 arasında 50.400 saniye var, saniyeleri rastgele hale getirmek de biraz daha karmaşık olurdu. Son olarak, başlangıç ​​zamanları rastgele ve birbirinden bağımsız olduğundan, komut dosyasının iki veya daha fazla örneğinin aynı anda başlatılması mümkündür (ancak pek olası değildir).


2
Dolar işaretini bırakıp çift parenleri sola hareket ettirerek (örneğin ((maxdelay = 14 * 60))veya ((delay = $RANDOM % maxdelay))) aritmetik atamaları daha okunaklı hale getirebilirsiniz . sleepArgümanı hala (istenirse Eğer boşluk ekleyebilirsiniz rağmen) sende yolu olması gerekiyor.
sonraki duyuruya kadar duraklatıldı.

1
Bu benim için de çalıştı. Benim özel bash sleep $[ ( $RANDOM % 60 ) + 1 ]s && some_script.sh
betiğim

Bir şey mi eksik yoksa maksimum gecikme maxdelay = $ ((14 *
60/20

@jenishSakhiya 20 koşunun her biri için rastgele gecikmeler mutlaktır (iyi, sabah 9'da başlar), başka bir koşuya göre değil. Yani, rastgele gecikmelerden biri 13 saat olarak gelirse, bu, diğer çalışmalardan 13 saat sonra değil, akşam 10'da (09: 00'dan 13 saat sonra) çalışacağı anlamına gelir.
Gordon Davisson

143

Evet, evet, soru bir yıldan eski, ama belki işe yarar bir şeyler ekleyebilirim:

Bir şeyi günde 20 kez sabah 9 ile akşam 11 arasında rastgele bir farkla nasıl kaydedebilirim? Bu cron içinde biraz zor çünkü 14 saati 20 yürütme süresine bölüyorsunuz. Diğer cevapları pek sevmiyorum çünkü php betiğiniz için bir bash sarmalayıcı komut dosyası yazmayı gerektiriyorlar.

Bununla birlikte, zamanlama ve frekans kısıtlamasını 8:30 am ve 23:09 pm arasında 13 kez azaltma özgürlüğüne izin verirseniz, bu hile yapabilir ve hepsi crontab'inizin sınırları dahilinde:

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

$ {RANDOM: 3: 2} bash'ın yukarıda bahsettiği $ RANDOM'unu kullanır, ancak bash dizi dilimlemeyi ekler. Bash değişkenleri tiplenmemiş olduğundan, sözde rastgele işaretli 16 bitlik sayı, 5 ondalık basamağının ilk 2'sine kesilerek, cronjob'unuzu 10 ila 99 dakika arasında geciktirmek için size kısa ve öz bir tek satırlık verir (ancak dağıtım, 10 ila 32).

Aşağıdakiler de sizin için işe yarayabilir, ancak bazı nedenlerden dolayı "daha az rastlantısal" olduğunu buldum (belki de Benford Yasası sözde rastgele sayıların modüle edilmesiyle tetikleniyor. Hey, bilmiyorum, matematiği boşverdim ... Suçla bash üzerinde!):

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

Modülüsünü yukarıdaki '\%' olarak göstermeniz gerekir çünkü cron (en azından Linux 'vixie-cron'), çıkış karaktersiz bir '%' ile karşılaştığında satırı sonlandırır.

Belki kalan 7 komut dosyası yürütmesini başka bir 7 saatlik aralıkla başka bir satır ekleyerek elde edebilirsiniz. Ya da 03:00 ile 23:00 arasında koşmak için kısıtlamanızı gevşetin.


4
Geç cevabı beğendim. Ancak, 10 ila 99 aralığında eşit olarak dağıtılmış rastgele bir tam sayı oluşturmaya çalışıyorsanız ve RASGELE'nin çıktısı 0 ila 32.767 ise, neden yapmayasınız $[(RANDOM/368)+10]?
jsdalton

3
@jsdalton: Modulo operatörü daha iyi olmaz mıydı? $((RANDOM % 90 + 10))Test:for i in {0..9999}; do echo $((RANDOM % 90 + 10)); done | sort | uniq -c
geon

5
O bashism önlemek için daha iyi olabilir pek çok sistemlerde cron varsayılan olarak bash kullanmaz $RANDOM: sleep $(( $(od -N1 -tuC -An /dev/urandom) \% 90 ))m.
pabouk

9
crontabKullanmadan bashönce kullandığınızdan emin olun $RANDOM. Varsa vixie-cron(Ubuntu'da benim durumum gibi görünüyor), o zaman SHELL=/bin/bashen üste ekleyebilirsiniz . Diğer cron sürümleri için burada daha fazla alternatif var: superuser.com/a/264541/260350
DaAwesomeP

1
Yukarıdaki ilk öneriyi kullandığımda, crontab: errors in crontab file, can't install. Do you want to retry the same edit?lütfen yardım alıyorum
Seano

73

Bu yüzden 1AM ile 330AM arasında bir komut çalıştırmak için aşağıdakileri kullanıyorum

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

Bu benim için rastgele ihtiyaçlarımı karşılıyor. Bu 9000 saniye == 150 dakika == 2,5 saat


8
:: MindBLOWN :: biraz perl kullanmak için başka bir belirsiz yer.
Mark Carpenter Jr

Bu kesinlikle en temiz cevap
Enrico Detoma

Yine de, birçok süreç yarattığınız için bu biraz verimsiz.
kahveciderin

21

Cron bir RANDOM_DELAYdeğişken sunar . Ayrıntılar crontab(5)için bakın.

RANDOM_DELAY değişkeni, iş başlangıcını, değişken tarafından belirlenen üst sınırla rastgele dakika miktarıyla geciktirmeye izin verir.

Bu, anacronişlerde yaygın olarak görülür , ancak aynı zamanda bir crontab.

İnce (dakika) ayrıntı düzeyinde çalışan bazı işleriniz ve kaba işleriniz varsa, buna dikkat etmeniz gerekebilir.


RANDOM_DELAY değişkenini kullanmayı çok isterdim, ancak Ubuntu 14.04.4 LTS'de crontab (5) 'in kılavuz sayfasında herhangi bir ipucu bulamıyorum.
Exocom

Bu talihsizlik. Orada desteklenip desteklenmediğini merak ediyorum. Centos 7 ve Arch Linux'taki o kılavuzda belgelendiğini görüyorum.
Micah Elliott

9
bu doğru cevap gibi görünüyor ama bir örnek verebilir misiniz?
chovy

14
Lütfen bunun RANDOM_DELAYbir kez kurulduğunu ve arka plan programının tüm çalışma süresi boyunca sabit kaldığını unutmayın .
Maciej Swic

5
RANDOM_DELAYBayrak ait özelliğidir Cronie-Crond Ubuntu çalışıyor gibi görünüyor iken vixie-cronbu bayrağı yoksun olan.
kravietz

7

İlk düşüncem, 20 iş için rastgele planlanmış bir cron işi oluşturmaktı. Yardımcı atprogram (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) komutları belirtilen zamanda çalıştırmak için kullanılır.


At kullanımına bir örnek burada: stackoverflow.com/a/6136145/803174
Kangur

7

Kullanmaya son verdim sleep $(( 1$(date +%N) % 60 )) ; dostuffs(bash & sh ile uyumlu)

1 önek, tarih +% N'nin 8 tabanlı OLMAYAN yorumlamasını zorlamaktır (ör. 00551454)

Bir crontab dosyasında \% kullanarak% 'dan çıkmayı unutmayın

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

2
Birisi merak ederse, benim gibi:% N güncel nanolar sağlar, ancak bazı man sayfalarında bunun için bilgi eksiktir. Bu, komut başına kolayca "biraz rastgeleliğe" ihtiyaç duyan insanlar için çok akıllı bir çözümdür.
Thorsten Schöning

Halihazırda başka yerlerde ele alınan uyarıların dışında, bu yalnızca dateGNU'ya sahipseniz işe yarar (muhtemelen çoğu Linux'ta yaptığınız, ancak Busybox, standart MacOS veya diğer çeşitli BSD'den türetilmiş platformlarda değil).
üçlü

4

al-x'in Çözümü benim için çalışmıyor çünkü crontab komutları bash'de değil, sanırım sh'de çalıştırılıyor. Ne anlama geliyor:

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

Her şeyi denedim ve hala benim için işe yaramadı. Nedenini açıkladınız, teşekkürler!
marlar

$[ ... ]waaaay geri geldiğinden beri kullanımdan kaldırılmış sözdizimi; bu milenyumdan kalan herhangi bir şey için, $((RANDOM\%90))mhangisinin POSIX uyumlu sözdizimi olduğunu tercih edersiniz (ama elbette RANDOMhala yalnızca Bash'dir).
üçlü

1

at -f [file] [timespec]

veya

echo [command] | at [timespec]

veya

at [timespec]... ve scriptkaydı gibi etkileşimli özellikler .

Komut

Çalıştırıldığında metin stdin'de veya ile belirtilen dosyada sağlanır -f [file].

Zaman aralığı

İşte [timespec] gramer . Şunun gibi bir şey olabilir:

  • 24 saatlik zaman örneğin 4-basamaklı int olarak 0100, 2359,1620
  • now + 10 minutes
  • 2071-05-31 - 5 hours 12 minutes UTC

Saat dilimini açıkça belirtiyorsanız, zaman belirtiminin bazı sürümleri yalnızca UTCisteğe bağlı saat dilimi bağımsız değişkenine izin verebilir .

Misal

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

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

Denemek...

(Boru) ' echoyu önceden bekleyerek ve kaçarak bash ayrıştırmasını test edebilirsiniz |.

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

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

Planlanan işleri görmek için, atqiş içeriğini (ortam değişkenleri, kurulum ve komut / komut dosyası) ile kullanın at -c [jobid].

Not

Sistem cron'un bir parçasıdır ve etkileşimli komut istemi aslında kabuğunuzun tüm mevcut durumunu yakalar, böylece komutları mutlak yollar belirlemeden çalıştırabilirsiniz.


1

Bunun daha eski bir iş parçacığı olduğunun farkındayım, ancak çok kullandığım rastgele değerle ilgili bir şey eklemek istiyorum. $ RANDOM değişkenini sabit ve sınırlı bir aralıkla kullanmak yerine, genellikle kabukta rastgele aralıklı rasgele değerler yaparım.

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

örneğin şunları yapabilirsiniz:

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

ve bu ileti dizisinde tartışılan bazı kısıtlamaların üstesinden gelin.


1
SO'ya hoş geldiniz. Şey, eski iş parçacığı ya da değil, bu beni yolladı ~$info ddve sol tarafında neler olduğunu anlayabiliyorum |, ancak sağ tarafı ayırt edemiyorum. Öyleyse, ben ve overcoming some restrictionsrastgele değer üretmeyle ilgilenen diğerleri için , neden biraz zaman ayırıp RHS'yi açıklamayalım ve yaklaşımınızı kullanmak için daha güçlü bir adım atmayasınız? Açıklamanın derinliği hem önerdiğiniz süreç konusunda insanları rahatlatır hem de faydaları Teşekkürler.
Chris

1
Ah tamam. od aka "sekizli döküm" bir dosya veya stdin alır ve ikili verileri insan tarafından okunabilir biçimde döker. Numaramızın işaretsiz ondalık (-t u4) olarak gösterilmesini istiyoruz ve adres indeksini (-A yok) istemiyoruz. Sadece 4 bayt aldığımız için -N4 gereksizdir, ancak zarar da vermez. Umarım bu bunu açıklar ...
MLP

0

Burada yolu araştıranlar için:

Anacron kullanıyorsanız (Ubuntu masaüstü ve dizüstü bilgisayar), o zaman düzenleyebilirsiniz

/etc/anacrontab

ve Ekle

RANDOM_DELAY=XX 

XX, temel işi ertelemek istediğiniz dakika miktarıdır.

Anacron cron gibidir, ancak bilgisayarınızın 7x24 açık olmasını beklemiyor (dizüstü bilgisayarlarımız gibi) ve sistem çöktüğü için kaçırdığı komut dosyalarını çalıştıracak.


0

Bu örnekle komutu çalıştırmadan önce rastgele zamanlar kullanmayı deneyebilirsiniz:

#!/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

Her gün crontab'ı yeniden yazan bir betik oluşturmaya ne dersiniz?

  1. Mevcut cronları oku (A)
  2. Rastgele zamanlar seçin (B)
  3. Önceki cronları (A) yeniden yazın, yeni rastgele cronlar ekleyin (B)
  4. Bu betiği ilk etapta çalıştırmak için cron'a eklediğinizden emin olun.

2
Yanıt olarak yorum göndererek itibar sistemini bozmayın. Kişisel comment ancak aslında iyi yeterli görünüyor olması bir cevap. " Yorum eklemek için temsilcim yok, ancak " seçeneğini kaldırmanızı öneririm .
Ted Lyngmo

1
Bu yanıtı az önce gözden geçirdim ve sonunda soru sorduğunuz kısmı kaçırdım (benim açımdan özensiz çalışma). Cevaplarda soru sormayın. Sahip olduğunuz sorular için kendi sorunuzu gönderin. Yarı sorunuzu cevap olarak geçebilecek bir şeye dönüştürdüm.
Ted Lyngmo

1
Anladım! Teşekkürler. Bir dahaki sefere daha dikkatli olacağım, kötü niyet söz konusu değildi.
mellofellow

1
Eminim kötü niyetin yoktu ve aşırı dikkatli olmana gerek yok. Olası bir çözümün ana hatlarını belirlediniz ve sonunda biraz tökezlediniz. Telaşa gerek yok!
Ted Lyngmo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.