Cron завдання та випадковий час, протягом заданих годин


100

Мені потрібна можливість запускати PHP-скрипт 20 разів на день в абсолютно випадковий час. Я також хочу, щоб він працював лише з 9:00 до 23:00.

Я знайомий зі створенням робочих місць у Linux.


1
Питання поставлене не дуже вдало. Врешті-решт ви хочете розподілити 20 точок на осі часу між 9:00 та 11:00. Але чи існують обмеження щодо мінімальної різниці в часі? Чи нічого не робити між 9:00 та 10:30 ранку? Єдиний спосіб зробити це прийнятно, здається ідеї Клауса: вибрати свої 20 разів о 09:00, що дозволить вам виконати будь-які обмеження, які у вас можуть бути, а потім запланувати речі з "на".
David Tonhofer

Відповіді:


38

Якщо я розумію, що ви шукаєте, вам потрібно буде зробити дещо безладно, наприклад, мати роботу cron, яка запускає скрипт bash, який рандомізує час запуску ... Щось на зразок цього:

crontab:

0 9 * * * /path/to/bashscript

та в / 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

Кілька приміток: цей підхід трохи марнотратний, оскільки він запускає 20 фонових процесів о 9 ранку, кожен з яких чекає випадкову кількість хвилин (до 14 годин, тобто 23 вечора), після чого запускає php-скрипт і виходи. Крім того, оскільки він використовує випадкову кількість хвилин (а не секунд), час початку не є настільки випадковим, як це могло б бути. Але $ RANDOM піднімається лише до 32 767, а між 9:00 та 23:00 - 50 400 секунд, було б трохи складніше також рандомизувати секунди. Нарешті, оскільки час запуску випадковий і незалежний один від одного, можливо (але не дуже ймовірно), що два або більше екземплярів сценарію будуть запущені одночасно.


2
Ви можете зробити арифметичні завдання більш читабельними, опустивши знак долара та перемістивши подвійні парени вліво (наприклад, ((maxdelay = 14 * 60))або ((delay = $RANDOM % maxdelay))). sleepАргумент ще повинен бути шлях у вас є (хоча ви можете додати прогалини, якщо це необхідно).
Призупинено до подальшого повідомлення.

Це спрацювало і у мене. Мій власний скрипт bash виглядає так, як sleep $[ ( $RANDOM % 60 ) + 1 ]s && some_script.sh
показано

Мені чогось не вистачає або максимальну затримку слід встановити на maxdelay = $ ((14 *
60/20

@jenishSakhiya Випадкові затримки для кожного з 20 прогонів є абсолютними (ну, починаючи з 9 ранку), а не відносно іншого з прогонів. Тобто, якщо одна із випадкових затримок виявиться як 13 годин, це означає, що вона працюватиме о 22:00 (13 годин після 9:00), а не через 13 годин після будь-якої іншої роботи.
Гордон Девіссон,

138

Так, так, питанню вже більше року, але, можливо, я можу додати щось корисне:

Як хрон щось у випадковому зміщенні 20 разів на день між 9:00 та 23:00? Це досить складно в рамках cron, тому що ви ділите 14 годин на 20 разів виконання. Інші відповіді мені не дуже подобаються, тому що вони вимагають написання сценарію обгортки bash для вашого php-сценарію.

Однак, якщо ви дозволите мені полегшити обмеження часу та частоти до 13 разів з 8:30 до 23:09, це може зробити трюк, і все в межах вашого crontab:

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

$ {RANDOM: 3: 2} використовує $ RANDOM bash, про що згадували інші люди, але додає нарізування масиву bash. Оскільки змінні bash нетипізовані, псевдовипадкове підписане 16-бітове число скорочується до перших 2 з 5 десяткових цифр, що дає вам стислий однорядковий вкладиш для затримки вашого cronjob між 10 і 99 хвилинами (хоча розподіл упереджений до Від 10 до 32).

Наступне може також підійти для вас, але я виявив, що воно з якихось причин виявляється "менш випадковим" (можливо, закон Бенфорда ініціюється модуляцією псевдовипадкових чисел. Гей, я не знаю, я зірвався з математикою ... Звинувачуй це на баш!):

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

Вам потрібно відобразити модуль як '\%' вище, оскільки cron (ну, принаймні, Linux 'vixie-cron') закінчує рядок, коли зустрічає нескопійований '%'.

Можливо, ви могли б там залишити 7 виконань скриптів, додавши ще один рядок з іншим 7-годинним діапазоном. Або розслабте своє обмеження, щоб бігати між 3 ранку та 23 вечора.


4
Мені подобається пізня відповідь. Але якщо ви намагаєтеся сформувати випадкове ціле число, рівномірно розподілене в діапазоні від 10 до 99, а результат RANDOM становить від 0 до 32 767, чому б вам просто не зробити це $[(RANDOM/368)+10]?
jsdalton

3
@jsdalton: Чи не буде оператор за модулем кращим? $((RANDOM % 90 + 10))Тест:for i in {0..9999}; do echo $((RANDOM % 90 + 10)); done | sort | uniq -c
geon,

5
У багатьох системах хрон не використовує Баш за замовчуванням , так що може бути краще , щоб уникнути bashism $RANDOM: sleep $(( $(od -N1 -tuC -An /dev/urandom) \% 90 ))m.
pabouk

9
Переконайтеся, що crontabвикористовується bashперед використанням $RANDOM. Якщо у вас є vixie-cron(здається, це моя справа в Ubuntu), ви можете додати SHELL=/bin/bashдо початку. Тут є інші альтернативи для інших версій cron: superuser.com/a/264541/260350
DaAwesomeP

1
Коли я використовую першу пропозицію вище, я отримую crontab: errors in crontab file, can't install. Do you want to retry the same edit?допомогу
Seano

72

Отже, я використовую наступне для запуску команди між 1 ранку та 330 ранку

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

Це піклується про мої випадкові потреби в мені. Це 9000 секунд == 150 хвилин == 2,5 годин


8
:: MindBLOWN :: ще одне незрозуміле місце, де можна використати трохи perl.
Марк Карпентер-молодший,

Це, безумовно, найчистіша відповідь
Енріко Детома,

Однак це наче неефективно, оскільки ви створюєте багато процесів.
kahveciderin

21

Cron пропонує RANDOM_DELAYзмінну. Детальніше crontab(5)див.

Змінна RANDOM_DELAY дозволяє затримувати запуски завдань випадковою кількістю хвилин з верхньою межею, заданою змінною.

Це часто спостерігається на anacronробочих місцях, але також може бути корисним у crontab.

Можливо, вам доведеться бути обережним із цим, якщо у вас є деякі завдання, які виконуються з точною (щохвилинною) деталізацією, а інші грубі.


Я хотів би використовувати змінну RANDOM_DELAY, але не можу знайти жодних підказок у керівництві crontab (5) в Ubuntu 14.04.4 LTS.
Exocom,

Це прикро. Цікаво, чи це там не підтримується. Я бачу, що це задокументовано на цій сторінці на Centos 7 та Arch Linux.
Micah Elliott

9
це здається правильною відповіддю, але чи можете ви навести приклад?
chovy

14
Зверніть увагу, що RANDOM_DELAYвстановлюється один раз і залишається незмінним протягом усього часу роботи демона.
Maciej Swic

5
RANDOM_DELAYПрапор особливість cronie-crond в той час як Ubuntu , здається, працює в vixie-cronякому відсутній цей прапор.
kravietz

7

Моєю першою думкою було б створити одне завдання cron, запускаючи 20 випадково запланованих на робочих місцях. atКорисності (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) використовуються для виконання команд в заданий час.


Приклад використання at знаходиться тут: stackoverflow.com/a/6136145/803174
Кангур

6

У підсумку я використав sleep $(( 1$(date +%N) % 60 )) ; dostuffs (сумісно з bash & sh)

Префікс 1 призначений для примусової інтерпретації бази NON 8 дати +% N (наприклад, 00551454)

Не забудьте уникнути%, використовуючи \% у файлі crontab

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

2
Якщо хтось дивується, як я:% N надає поточні наносистеми, але на деяких сторінках людей для цього не вистачає інформації. Це дуже розумне рішення для людей, яким просто потрібна "деяка випадковість" для кожної команди.
Торстен Шенінг,

Окрім застережень, які вже розглядалися в інших місцях, це буде працювати, лише якщо у вас є GNU date(що ви, мабуть, робите на більшості Linux, але не на Busybox, стандартному MacOS чи інших платформах, похідних від BSD).
тричі

4

Рішення al-x у мене не працює, оскільки команди crontab виконуються не в bash, а в sh я думаю. Що означає робота:

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

Я все пробував, і все одно у мене не виходило. Ви допис пояснили чому, дякую!
марлар

$[ ... ]є застарілим синтаксисом, оскільки waaaay назад; для будь-чого з цього тисячоліття ви віддаєте перевагу, $((RANDOM\%90))mякий є сумісним з POSIX синтаксисом (але, звичайно RANDOM, все ще лише Bash).
потрійний

1

at -f [file] [timespec]

або

echo [command] | at [timespec]

або

at [timespec] ... та інтерактивна специфікація, як script запис.

Командування

Під час запуску текст надає на stdin або у файлі, вказаному-f [file] .

Timespec

Ось [timespec] граматика . Це може бути щось на зразок:

  • 24-годинний час , як 4-значного міжнар, наприклад 0100, 2359,1620
  • now + 10 minutes
  • 2071-05-31 - 5 hours 12 minutes UTC

Якщо ви чітко вказуєте часовий пояс, деякі версії можуть лише дозволятиUTC необов’язковий аргумент часового поясу.

Приклад

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

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

Спробуй...

Ви можете протестувати синтаксичний аналіз bash, попередньо очікуючи на echoвхід і витягнувши |(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

Щоб побачити заплановані завдання, використовуйте atqта вміст завдань (vars середовища, налаштування та команди / сценарії) за допомогою at -c [jobid].

Примітка

Система є частиною cron, і інтерактивне підказка фактично фіксує весь поточний стан вашої оболонки, тому ви можете запускати команди, не вказуючи абсолютних шляхів.


0

Для тих, хто погуглив сюди:

Якщо ви використовуєте anacron (робочий стіл та ноутбук Ubuntu), тоді ви можете редагувати

/etc/anacrontab

і додати

RANDOM_DELAY=XX 

Де XX - кількість хвилин, яку потрібно відкласти на базове завдання.

Anacron схожий на cron, але він не очікує, що ваш комп’ютер буде працювати в режимі 24x7 (як наші ноутбуки) і буде запускати скрипти, які він пропустив, оскільки система не працювала.


0

За допомогою цього прикладу можна спробувати використовувати випадкові випадки перед виконанням команди:

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

А як щодо створення сценарію, який щодня переписує crontab?

  1. Зчитування поточних крон (A)
  2. Вибір випадкових часів (B)
  3. Перепишіть попередні крони (A), додайте нові випадкові карони (B)
  4. Не забудьте додати до cron, щоб запустити цей сценарій.

2
Не обходьте систему репутації, публікуючи коментарі як відповіді. Однак ваш коментар виглядає досить добре, щоб насправді бути відповіддю. Я рекомендую видалити "У мене немає представника, щоб додати коментар, але ".
Тед Лінгмо,

1
Я щойно переглянув цю відповідь і пропустив ту частину, в якій ви задаєте питання взамін наприкінці (неакуратна робота з мого боку). Не задавайте запитань у відповідях. Опублікуйте власне запитання щодо своїх питань. Я перетворив ваше напівзапитання на щось, що може передати відповідь.
Тед Лінгмо,

1
Зрозумів! Дякую. Наступного разу я буду обережнішим, не маючи на увазі жодних намірів.
mellofellow

1
Я впевнений, у вас не було злих намірів, і вам не потрібно бути надмірно обережним. Ви окреслили можливе рішення - і трохи запнулись наприкінці. Не хвилюйтесь!
Тед Лінгмо,

0

Я усвідомлюю, що це старіший ланцюжок, але я хочу додати одну річ, пов’язану з випадковими значеннями, яку я часто використовую. Замість того, щоб використовувати змінну $ RANDOM із фіксованим та обмеженим діапазоном, я часто роблю випадкові значення довільного діапазону в оболонці з

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

так що ви можете зробити, наприклад,

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

і подолати деякі обмеження, про які йшлося в цій темі.


1
Ласкаво просимо до SO. Ну, стара тема чи ні, це мене відправило, ~$info ddі я можу зрозуміти, що відбувається з лівого боку |, але не можу розібрати правого. Отже, для мене та інших, хто зацікавлений у overcoming some restrictionsгенерації випадкових значень, чому б не взяти хвилину, щоб пояснити RHS, і зробити сильніший крок для використання вашого підходу. Поглиблене пояснення робить людей комфортними як для запропонованого вами процесу, так і для його переваг. Дякую.
Кріс

Ну гаразд. od aka "вісімковий дамп" бере файл або stdin і скидає двійкові дані в зручну для читання форму. Ми хочемо, щоб наш номер відображався як десятковий знак без знака (-t u4), і не хочемо, щоб індекс адреси (-A жоден). -N4 є зайвим, оскільки ми беремо лише 4 байти, але також не шкодить. Сподіваюся, це пояснює це ...
MLP
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.