Saya membutuhkan kemampuan untuk menjalankan skrip PHP 20 kali sehari pada waktu yang benar-benar acak. Saya juga ingin itu hanya berjalan antara jam 9 pagi - 11 malam.
Pertanyaannya tidak diajukan dengan baik. Akhirnya Anda ingin mendistribusikan 20 titik pada sumbu waktu antara jam 9 pagi dan 11 pagi. Tetapi apakah ada kendala pada perbedaan waktu minimum? Apakah tidak melakukan apa pun antara pukul 09.00 dan 10.30 diperbolehkan? Satu-satunya cara untuk melakukan ini menurut ide Klaus: pilih 20 waktu Anda pada pukul 09:00, yang memungkinkan Anda untuk memenuhi batasan apa pun yang mungkin Anda miliki, lalu jadwalkan hal-hal dengan "pada".
David Tonhofer
Jawaban:
38
Jika saya mengerti apa yang Anda cari, Anda perlu melakukan sesuatu yang sedikit berantakan, seperti memiliki tugas cron yang menjalankan skrip bash yang mengacak waktu proses ... Sesuatu seperti ini:
crontab:
09***/path/to/bashscript
dan di / path / ke / bashscript:
#!/bin/bash
maxdelay=$((14*60))# 14 hours from 9am to 11pm, converted to minutesfor((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 scriptdone
Beberapa catatan: pendekatan ini sedikit boros sumber daya, karena menjalankan 20 proses latar belakang pada jam 9 pagi, yang masing-masing menunggu beberapa menit secara acak (hingga 14 jam, yaitu jam 11 malam), kemudian meluncurkan skrip php dan keluar. Selain itu, karena ini menggunakan jumlah menit acak (bukan detik), waktu mulai tidak seacak mungkin. Tapi $ ACAK hanya naik menjadi 32.767, dan ada 50.400 detik antara jam 9 pagi dan 11 malam, akan sedikit lebih rumit untuk mengacak detik juga. Terakhir, karena waktu mulai acak dan tidak bergantung satu sama lain, mungkin (tetapi tidak sangat mungkin) dua atau lebih contoh skrip akan dimulai secara bersamaan.
Anda dapat membuat tugas aritmatika lebih mudah dibaca dengan menghilangkan tanda dolar dan memindahkan tanda kurung ganda ke kiri (mis. ((maxdelay = 14 * 60))Atau ((delay = $RANDOM % maxdelay))). The sleepArgumen masih perlu cara Anda memilikinya (meskipun Anda bisa menambahkan spasi, jika diinginkan).
Dijeda sampai pemberitahuan lebih lanjut.
1
Ini berhasil juga untuk saya. Skrip bash kustom saya terlihat seperti di bawah ini sleep $[ ( $RANDOM % 60 ) + 1 ]s && some_script.sh
Shyam Habarakada
Apakah saya melewatkan sesuatu atau penundaan maksimum harus diatur ke maxdelay = $ ((14 *
60/20
@jenishSakhiya Penundaan acak untuk masing-masing dari 20 sesi adalah mutlak (baik, mulai pukul 9 pagi), tidak relatif terhadap proses lainnya. Artinya, jika salah satu penundaan acak muncul sebagai 13 jam, itu berarti penundaan akan berjalan pada pukul 10 malam (13 jam setelah 9 pagi), bukan 13 jam setelah penundaan yang lain.
Gordon Davisson
139
Ya, ya, pertanyaannya sudah lebih dari satu tahun, tapi mungkin saya bisa menambahkan sesuatu yang berguna:
Bagaimana cara membuat sesuatu secara acak 20 kali sehari antara jam 9 pagi dan 11 malam? Itu agak rumit dalam cron, karena Anda membagi 14 jam dengan 20 kali eksekusi. Saya tidak terlalu menyukai jawaban lain karena mereka memerlukan penulisan skrip bash wrapper untuk skrip php Anda.
Namun, jika Anda mengizinkan saya untuk mengurangi pembatasan waktu dan frekuensi menjadi 13 kali antara jam 8:30 pagi dan 11:09 malam, ini mungkin berhasil, dan semuanya dalam batasan crontab Anda:
$ {ACAK: 3: 2} menggunakan $ ACAK bash yang telah disebutkan orang lain di atas, tetapi menambahkan bash array slicing. Karena variabel bash tidak diketik, angka 16-bit bertanda pseudo-random akan dipotong ke 2 pertama dari 5 digit desimalnya, memberi Anda satu baris ringkas untuk menunda cronjob Anda antara 10 dan 99 menit (meskipun distribusinya bias ke arah 10 hingga 32).
Hal berikut mungkin juga berhasil untuk Anda, tetapi menurut saya memang "kurang acak" karena beberapa alasan (mungkin Hukum Benford dipicu oleh pemodulasian bilangan acak semu. Hei, saya tidak tahu, saya gagal dalam matematika ... Salahkan di pesta!):
Anda perlu merender modulus sebagai '\%' di atas karena cron (yah, setidaknya Linux 'vixie-cron') mengakhiri baris ketika menemukan '%' yang tidak dapat dihilangkan.
Mungkin Anda bisa mendapatkan 7 eksekusi skrip yang tersisa di sana dengan menambahkan baris lain dengan rentang 7 jam lainnya. Atau kendurkan batasan Anda untuk berlari antara jam 3 pagi dan 11 malam.
Saya suka jawaban yang terlambat. Tetapi jika Anda mencoba untuk menghasilkan bilangan bulat acak yang didistribusikan secara merata dalam kisaran 10 hingga 99, dan keluaran RANDOM adalah 0 hingga 32.767, mengapa Anda tidak melakukannya $[(RANDOM/368)+10]?
jsdalton
3
@jsdalton: Bukankah operator modulo lebih baik? $((RANDOM % 90 + 10))Tes:for i in {0..9999}; do echo $((RANDOM % 90 + 10)); done | sort | uniq -c
geon
5
Pada banyak sistem cron tidak menggunakan bash secara default sehingga bisa lebih baik untuk menghindari bashism yang $RANDOM: sleep $(( $(od -N1 -tuC -An /dev/urandom) \% 90 ))m.
pabouk
9
Pastikan yang crontabdigunakan bashsebelum Anda menggunakan $RANDOM. Jika Anda memiliki vixie-cron(tampaknya kasus saya di Ubuntu), maka Anda dapat menambahkan SHELL=/bin/bashke atas. Ada lebih banyak alternatif untuk versi cron lainnya di sini: superuser.com/a/264541/260350
DaAwesomeP
1
Ketika saya menggunakan saran pertama di atas, saya mendapatkan crontab: errors in crontab file, can't install. Do you want to retry the same edit?bantuan
Seano
72
Jadi saya menggunakan yang berikut ini untuk menjalankan perintah antara 1AM dan 330AM
Variabel RANDOM_DELAY memungkinkan penundaan permulaan pekerjaan dengan jumlah menit acak dengan batas atas yang ditentukan oleh variabel.
Ini terlihat secara umum dalam anacronpekerjaan, tetapi juga dapat berguna dalam a crontab.
Anda mungkin perlu berhati-hati dengan ini jika Anda memiliki beberapa pekerjaan yang berjalan dengan perincian (menit) yang baik dan pekerjaan lain yang kasar.
Saya ingin menggunakan variabel RANDOM_DELAY, tetapi tidak dapat menemukan petunjuk apa pun di halaman manual crontab (5) di Ubuntu 14.04.4 LTS.
Exocom
Itu sangat disayangkan. Saya ingin tahu apakah itu tidak didukung di sana. Saya melihatnya didokumentasikan di halaman manual di Centos 7 dan Arch Linux.
Micah Elliott
9
ini sepertinya jawaban yang benar tetapi dapatkah Anda memberi contoh?
chovy
14
Harap dicatat bahwa RANDOM_DELAYitu dibuat sekali dan tetap konstan untuk seluruh runtime daemon.
Maciej Swic
5
The RANDOM_DELAYbendera adalah fitur dari cronie-crond sementara Ubuntu tampaknya berjalan vixie-cronyang tidak memiliki bendera ini.
kravietz
7
Pikiran pertama saya adalah membuat satu pekerjaan cron yang meluncurkan 20 pekerjaan yang dijadwalkan secara acak. The atutilitas (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) digunakan untuk mengeksekusi perintah pada waktu yang ditentukan.
Jika seseorang bertanya-tanya, seperti saya:% N memberikan nanos saat ini, tetapi beberapa halaman manual kekurangan informasi untuk itu. Ini adalah solusi yang sangat cerdas untuk orang-orang yang hanya membutuhkan "beberapa keacakan" dengan mudah per perintah.
Thorsten Schöning
Terlepas dari peringatan yang sudah dibahas di tempat lain, ini hanya akan berfungsi jika Anda memiliki GNU date(yang mungkin Anda lakukan di sebagian besar Linux, tetapi tidak di Busybox, MacOS standar, atau berbagai platform turunan BSD lainnya).
tripleee
4
Solusi al-x tidak bekerja untuk saya karena perintah crontab tidak dijalankan di bash tetapi di sh saya kira. Apa yang berhasil adalah:
Saya mencoba segalanya dan tetap tidak berhasil. Anda memposting menjelaskan mengapa, terima kasih!
marlar
$[ ... ]sudah usang sintaks sejak waaaay kembali; untuk apa pun dari milenium ini, Anda akan lebih memilih $((RANDOM\%90))msintaks yang kompatibel dengan POSIX (tetapi tentu saja RANDOMmasih hanya Bash).
tripleee
1
at -f [file] [timespec]
atau
echo [command] | at [timespec]
atau
at [timespec] ... dan spesifikasi interaktif seperti script rekaman.
Perintah
At menjalankan teks yang disediakan di stdin atau dalam file yang ditentukan oleh -f [file].
Waktu 24 jam sebagai 4-digit int, misalnya 0100, 2359,1620
now + 10 minutes
2071-05-31 - 5 hours 12 minutes UTC
Jika Anda secara eksplisit menentukan zona waktu, beberapa versi timespec mungkin hanya memungkinkan UTCuntuk argumen zona waktu opsional.
Contoh
cat script.sh | at now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes
at -f script.sh now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes
Cobalah ...
Anda dapat menguji penguraian bash dengan melakukan pra-tunggu echodan keluar dari |(pipa).
echo cat script.sh \| at now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes
echo at -f script.sh now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes
Untuk melihat pekerjaan yang dijadwalkan, gunakan atqdan isi pekerjaan (lingkungan vars, setup, dan perintah / skrip) dengan at -c [jobid].
Catatan
Sistem adalah bagian dari cron, dan prompt interaktif benar-benar menangkap seluruh status shell Anda saat ini, sehingga Anda dapat menjalankan perintah tanpa menentukan jalur absolut.
Jika Anda menggunakan anacron (desktop dan laptop Ubuntu), Anda dapat mengedit
/etc/anacrontab
dan tambahkan
RANDOM_DELAY=XX
Di mana XX adalah jumlah menit Anda ingin menunda pekerjaan dasar.
Anacron seperti cron tetapi tidak mengharapkan komputer Anda dalam 24x7 (seperti laptop kami) dan akan menjalankan skrip yang terlewat karena sistem sedang down.
Jangan mengelak dari sistem reputasi dengan memposting komentar sebagai jawaban. Namun komentar Anda terlihat cukup bagus untuk benar - benar menjadi jawaban. Saya sarankan untuk menghapus " Saya tidak memiliki perwakilan untuk menambahkan komentar, tapi ".
Ted Lyngmo
1
Saya baru saja meninjau jawaban ini dan melewatkan bagian di mana Anda mengajukan pertanyaan sebagai imbalan di bagian akhir (pekerjaan ceroboh di pihak saya). Jangan bertanya dalam jawaban. Posting pertanyaan Anda sendiri untuk pertanyaan yang Anda miliki. Saya membuat pertanyaan semi Anda menjadi sesuatu yang bisa menjadi jawaban.
Ted Lyngmo
1
Mengerti! Terima kasih. Saya akan lebih berhati-hati lain kali, tidak ada niat buruk yang dimaksudkan.
mellofellow
1
Saya yakin Anda tidak memiliki niat buruk dan Anda tidak perlu terlalu berhati-hati. Anda menguraikan solusi yang mungkin - dan sedikit tersandung di bagian akhir. Jangan khawatir!
Ted Lyngmo
0
Saya menyadari ini adalah utas yang lebih lama, tetapi saya ingin menambahkan satu hal terkait nilai acak yang sering saya gunakan. Alih-alih menggunakan variabel $ RANDOM dengan rentang tetap dan terbatas, saya sering membuat nilai acak rentang acak di shell dengan
dd if=/dev/urandom bs=4 count=12>/dev/null | od -N4 -t u4 -A none
jadi Anda bisa melakukannya, misalnya,
FULLRANDOM=$(dd if=/dev/urandom bs=4 count=12>/dev/null | od -N4 -t u4 -A none)
dan mengatasi beberapa batasan yang dibahas di utas ini.
Selamat datang di SO. Nah, utas lama atau tidak, ini mengirim saya ke ~$info dddan saya bisa mengerti apa yang terjadi di sisi kiri |, tetapi tidak bisa melihat sisi kanan. Jadi, bagi saya dan orang lain yang tertarik pada overcoming some restrictionspembuatan nilai acak, mengapa tidak meluangkan waktu sejenak untuk menjelaskan RHS, dan membuat promosi yang lebih kuat untuk menggunakan pendekatan Anda. Kedalaman penjelasannya membuat orang nyaman dengan proses yang Anda sarankan dan manfaatnya. Terima kasih.
Chris
Ah ok. od aka "octal dump" mengambil file atau stdin dan membuang data biner dalam bentuk yang dapat dibaca manusia. Kami ingin nomor kami ditampilkan sebagai desimal tak bertanda (-t u4), dan tidak ingin indeks alamat (-A tidak ada). -N4 adalah redundan karena kami hanya mengambil 4 byte, tetapi juga tidak merugikan. Saya harap ini menjelaskannya ...
Jawaban:
Jika saya mengerti apa yang Anda cari, Anda perlu melakukan sesuatu yang sedikit berantakan, seperti memiliki tugas cron yang menjalankan skrip bash yang mengacak waktu proses ... Sesuatu seperti ini:
crontab:
dan di / path / ke / bashscript:
Beberapa catatan: pendekatan ini sedikit boros sumber daya, karena menjalankan 20 proses latar belakang pada jam 9 pagi, yang masing-masing menunggu beberapa menit secara acak (hingga 14 jam, yaitu jam 11 malam), kemudian meluncurkan skrip php dan keluar. Selain itu, karena ini menggunakan jumlah menit acak (bukan detik), waktu mulai tidak seacak mungkin. Tapi $ ACAK hanya naik menjadi 32.767, dan ada 50.400 detik antara jam 9 pagi dan 11 malam, akan sedikit lebih rumit untuk mengacak detik juga. Terakhir, karena waktu mulai acak dan tidak bergantung satu sama lain, mungkin (tetapi tidak sangat mungkin) dua atau lebih contoh skrip akan dimulai secara bersamaan.
sumber
((maxdelay = 14 * 60))
Atau((delay = $RANDOM % maxdelay))
). Thesleep
Argumen masih perlu cara Anda memilikinya (meskipun Anda bisa menambahkan spasi, jika diinginkan).sleep $[ ( $RANDOM % 60 ) + 1 ]s && some_script.sh
Ya, ya, pertanyaannya sudah lebih dari satu tahun, tapi mungkin saya bisa menambahkan sesuatu yang berguna:
Bagaimana cara membuat sesuatu secara acak 20 kali sehari antara jam 9 pagi dan 11 malam? Itu agak rumit dalam cron, karena Anda membagi 14 jam dengan 20 kali eksekusi. Saya tidak terlalu menyukai jawaban lain karena mereka memerlukan penulisan skrip bash wrapper untuk skrip php Anda.
Namun, jika Anda mengizinkan saya untuk mengurangi pembatasan waktu dan frekuensi menjadi 13 kali antara jam 8:30 pagi dan 11:09 malam, ini mungkin berhasil, dan semuanya dalam batasan crontab Anda:
$ {ACAK: 3: 2} menggunakan $ ACAK bash yang telah disebutkan orang lain di atas, tetapi menambahkan bash array slicing. Karena variabel bash tidak diketik, angka 16-bit bertanda pseudo-random akan dipotong ke 2 pertama dari 5 digit desimalnya, memberi Anda satu baris ringkas untuk menunda cronjob Anda antara 10 dan 99 menit (meskipun distribusinya bias ke arah 10 hingga 32).
Hal berikut mungkin juga berhasil untuk Anda, tetapi menurut saya memang "kurang acak" karena beberapa alasan (mungkin Hukum Benford dipicu oleh pemodulasian bilangan acak semu. Hei, saya tidak tahu, saya gagal dalam matematika ... Salahkan di pesta!):
Anda perlu merender modulus sebagai '\%' di atas karena cron (yah, setidaknya Linux 'vixie-cron') mengakhiri baris ketika menemukan '%' yang tidak dapat dihilangkan.
Mungkin Anda bisa mendapatkan 7 eksekusi skrip yang tersisa di sana dengan menambahkan baris lain dengan rentang 7 jam lainnya. Atau kendurkan batasan Anda untuk berlari antara jam 3 pagi dan 11 malam.
sumber
$[(RANDOM/368)+10]
?$((RANDOM % 90 + 10))
Tes:for i in {0..9999}; do echo $((RANDOM % 90 + 10)); done | sort | uniq -c
$RANDOM
:sleep $(( $(od -N1 -tuC -An /dev/urandom) \% 90 ))m
.crontab
digunakanbash
sebelum Anda menggunakan$RANDOM
. Jika Anda memilikivixie-cron
(tampaknya kasus saya di Ubuntu), maka Anda dapat menambahkanSHELL=/bin/bash
ke atas. Ada lebih banyak alternatif untuk versi cron lainnya di sini: superuser.com/a/264541/260350crontab: errors in crontab file, can't install. Do you want to retry the same edit?
bantuanJadi saya menggunakan yang berikut ini untuk menjalankan perintah antara 1AM dan 330AM
Itu telah memenuhi kebutuhan acak saya untuk saya. Itu berarti 9.000 detik == 150 menit == 2,5 jam
sumber
Cron menawarkan
RANDOM_DELAY
variabel. Lihatcrontab(5)
detailnya.Ini terlihat secara umum dalam
anacron
pekerjaan, tetapi juga dapat berguna dalam acrontab
.Anda mungkin perlu berhati-hati dengan ini jika Anda memiliki beberapa pekerjaan yang berjalan dengan perincian (menit) yang baik dan pekerjaan lain yang kasar.
sumber
RANDOM_DELAY
itu dibuat sekali dan tetap konstan untuk seluruh runtime daemon.RANDOM_DELAY
bendera adalah fitur dari cronie-crond sementara Ubuntu tampaknya berjalanvixie-cron
yang tidak memiliki bendera ini.Pikiran pertama saya adalah membuat satu pekerjaan cron yang meluncurkan 20 pekerjaan yang dijadwalkan secara acak. The
at
utilitas (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) digunakan untuk mengeksekusi perintah pada waktu yang ditentukan.sumber
Saya akhirnya menggunakan
sleep $(( 1$(date +%N) % 60 )) ; dostuffs
(kompatibel dengan bash & sh)Awalan 1 adalah untuk memaksa interpretasi NON basis 8 tanggal +% N (misalnya 00551454)
Jangan lupa untuk keluar% menggunakan \% dalam file crontab
sumber
date
(yang mungkin Anda lakukan di sebagian besar Linux, tetapi tidak di Busybox, MacOS standar, atau berbagai platform turunan BSD lainnya).Solusi al-x tidak bekerja untuk saya karena perintah crontab tidak dijalankan di bash tetapi di sh saya kira. Apa yang berhasil adalah:
sumber
$[ ... ]
sudah usang sintaks sejak waaaay kembali; untuk apa pun dari milenium ini, Anda akan lebih memilih$((RANDOM\%90))m
sintaks yang kompatibel dengan POSIX (tetapi tentu sajaRANDOM
masih hanya Bash).at -f [file] [timespec]
atau
echo [command] | at [timespec]
atau
at [timespec]
... dan spesifikasi interaktif sepertiscript
rekaman.Perintah
At menjalankan teks yang disediakan di stdin atau dalam file yang ditentukan oleh
-f [file]
.Timespec
Berikut
[timespec]
tata bahasanya . Bisa jadi seperti ini:0100
,2359
,1620
now + 10 minutes
2071-05-31 - 5 hours 12 minutes UTC
Jika Anda secara eksplisit menentukan zona waktu, beberapa versi timespec mungkin hanya memungkinkan
UTC
untuk argumen zona waktu opsional.Contoh
cat script.sh | at now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes
at -f script.sh now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes
Cobalah ...
Anda dapat menguji penguraian bash dengan melakukan pra-tunggu
echo
dan keluar dari|
(pipa).echo cat script.sh \| at now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes
echo at -f script.sh now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes
Untuk melihat pekerjaan yang dijadwalkan, gunakan
atq
dan isi pekerjaan (lingkungan vars, setup, dan perintah / skrip) denganat -c [jobid]
.Catatan
Sistem adalah bagian dari cron, dan prompt interaktif benar-benar menangkap seluruh status shell Anda saat ini, sehingga Anda dapat menjalankan perintah tanpa menentukan jalur absolut.
sumber
Bagi yang googling caranya disini:
Jika Anda menggunakan anacron (desktop dan laptop Ubuntu), Anda dapat mengedit
dan tambahkan
Di mana XX adalah jumlah menit Anda ingin menunda pekerjaan dasar.
Anacron seperti cron tetapi tidak mengharapkan komputer Anda dalam 24x7 (seperti laptop kami) dan akan menjalankan skrip yang terlewat karena sistem sedang down.
sumber
Anda dapat mencoba dengan contoh ini untuk menggunakan waktu acak sebelum menjalankan perintah:
sumber
Bagaimana dengan membuat skrip yang menulis ulang crontab setiap hari?
sumber
Saya menyadari ini adalah utas yang lebih lama, tetapi saya ingin menambahkan satu hal terkait nilai acak yang sering saya gunakan. Alih-alih menggunakan variabel $ RANDOM dengan rentang tetap dan terbatas, saya sering membuat nilai acak rentang acak di shell dengan
jadi Anda bisa melakukannya, misalnya,
dan mengatasi beberapa batasan yang dibahas di utas ini.
sumber
~$info dd
dan saya bisa mengerti apa yang terjadi di sisi kiri|
, tetapi tidak bisa melihat sisi kanan. Jadi, bagi saya dan orang lain yang tertarik padaovercoming some restrictions
pembuatan nilai acak, mengapa tidak meluangkan waktu sejenak untuk menjelaskan RHS, dan membuat promosi yang lebih kuat untuk menggunakan pendekatan Anda. Kedalaman penjelasannya membuat orang nyaman dengan proses yang Anda sarankan dan manfaatnya. Terima kasih.