Cron công việc và thời gian ngẫu nhiên, trong những giờ nhất định


99

Tôi cần khả năng chạy một tập lệnh PHP 20 lần một ngày vào những thời điểm hoàn toàn ngẫu nhiên. Tôi cũng muốn nó chỉ chạy từ 9 giờ sáng đến 11 giờ tối.

Tôi đã quen với việc tạo cron job trong linux.


1
Câu hỏi không được đặt ra rất tốt. Cuối cùng, bạn muốn phân phối 20 điểm trên trục thời gian từ 9 giờ sáng đến 11 giờ sáng. Nhưng có những ràng buộc nào về chênh lệch thời gian tối thiểu không? Không làm gì từ 9 giờ sáng đến 10 giờ 30 sáng có được chấp nhận không? Cách duy nhất để làm điều này dường như có thể chấp nhận được theo ý tưởng của Klaus: chọn 20 lần của bạn lúc 09:00, cho phép bạn thực hiện bất kỳ ràng buộc nào bạn có thể có, sau đó lên lịch mọi thứ với "lúc".
David Tonhofer

Câu trả lời:


37

Nếu tôi hiểu những gì bạn đang tìm kiếm, bạn sẽ cần phải làm điều gì đó hơi lộn xộn, chẳng hạn như có một công việc cron chạy một tập lệnh bash ngẫu nhiên thời gian chạy ... Một cái gì đó như thế này:

crontab:

0 9 * * * /path/to/bashscript

và trong / 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

Một vài lưu ý: cách tiếp cận này hơi lãng phí tài nguyên vì nó kích hoạt 20 quy trình nền lúc 9 giờ sáng, mỗi quy trình chờ khoảng một số phút ngẫu nhiên (lên đến 14 giờ, tức 11 giờ tối), sau đó khởi chạy tập lệnh php và lối thoát hiểm. Ngoài ra, vì nó sử dụng một số phút ngẫu nhiên (không phải giây), thời gian bắt đầu không hoàn toàn ngẫu nhiên như chúng có thể. Nhưng $ RANDOM chỉ tăng lên đến 32.767 và có 50.400 giây trong khoảng thời gian từ 9 giờ sáng đến 11 giờ tối, sẽ phức tạp hơn một chút nếu ngẫu nhiên các giây. Cuối cùng, vì thời gian bắt đầu là ngẫu nhiên và độc lập với nhau, nên có thể (nhưng không có khả năng cao) rằng hai hoặc nhiều trường hợp của tập lệnh sẽ được bắt đầu đồng thời.


2
Bạn có thể làm cho các bài tập số học dễ đọc hơn bằng cách thả ký hiệu đô la và di chuyển dấu phẩy kép sang trái (ví dụ: ((maxdelay = 14 * 60))hoặc ((delay = $RANDOM % maxdelay))). Đối sleepsố vẫn cần theo cách bạn có (mặc dù bạn có thể thêm dấu cách, nếu muốn).
Tạm dừng cho đến khi có thông báo mới.

Điều này cũng làm việc cho tôi. Kịch bản ngoại hình tùy chỉnh bash tôi thích bên dưới sleep $[ ( $RANDOM % 60 ) + 1 ]s && some_script.sh
Shyam Habarakada

Am tôi thiếu một cái gì đó hoặc sự chậm trễ tối đa nên được thiết lập để maxdelay = $ ((14 * 60/20))
jenish Sakhiya

@jenishSakhiya Sự chậm trễ ngẫu nhiên cho mỗi lần chạy trong số 20 lần chạy là tuyệt đối (tốt, bắt đầu từ 9 giờ sáng), không liên quan đến các lần chạy khác. Nghĩa là, nếu một trong những sự chậm trễ ngẫu nhiên xuất hiện là 13 giờ, điều đó có nghĩa là nó sẽ chạy lúc 10 giờ tối (13 giờ sau 9 giờ sáng), không phải 13 giờ sau bất kỳ lần nào khác.
Gordon Davisson

138

Vâng, vâng, câu hỏi đã hơn một năm, nhưng có lẽ tôi có thể bổ sung một số điều hữu ích:

Làm thế nào để thu thập một thứ gì đó ở một khoảng thời gian bù trừ ngẫu nhiên 20 lần một ngày trong khoảng thời gian từ 9 giờ sáng đến 11 giờ tối? Điều đó khá phức tạp trong cron, bởi vì bạn đang chia 14 giờ cho 20 lần thực hiện. Tôi không thích các câu trả lời khác cho lắm vì chúng yêu cầu viết một tập lệnh trình bao bọc bash cho tập lệnh php của bạn.

Tuy nhiên, nếu bạn cho phép tôi tự do giảm giới hạn thời gian và tần suất xuống 13 lần trong khoảng thời gian từ 8:30 sáng đến 11:09 tối, thì điều này có thể thực hiện thủ thuật và tất cả đều nằm trong giới hạn của crontab của bạn:

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

$ {RANDOM: 3: 2} sử dụng $ RANDOM của bash mà những người khác đã đề cập ở trên, nhưng thêm tính năng cắt mảng bash. Vì các biến cơ sở không được định kiểu, nên số 16 bit có dấu giả ngẫu nhiên sẽ bị cắt ngắn thành 2 trong số 5 chữ số thập phân đầu tiên của nó, cung cấp cho bạn một lớp lót ngắn gọn để trì hoãn cronjob của bạn từ 10 đến 99 phút (mặc dù phân phối có xu hướng 10 đến 32).

Những điều sau đây cũng có thể phù hợp với bạn, nhưng tôi thấy nó "ít ngẫu nhiên hơn" vì một số lý do (có lẽ Định luật Benford được kích hoạt bằng cách điều chế các số giả ngẫu nhiên. Này, tôi không biết, tôi không thích toán học ... Đổ lỗi cho nó trên bash!):

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

Bạn cần kết xuất mô-đun như '\%' ở trên vì cron (tốt, ít nhất là Linux 'vixie-cron') kết thúc dòng khi nó gặp phải '%' không thoát.

Có thể bạn có thể nhận được 7 lần thực thi tập lệnh còn lại trong đó bằng cách thêm một dòng khác với phạm vi 7 giờ khác. Hoặc nới lỏng hạn chế chạy trong khoảng thời gian từ 3 giờ sáng đến 11 giờ đêm.


4
Tôi thích câu trả lời muộn. Nhưng nếu bạn đang cố gắng tạo một số nguyên ngẫu nhiên được phân phối đều trong phạm vi từ 10 đến 99 và đầu ra của RANDOM là 0 đến 32,767, tại sao bạn không làm $[(RANDOM/368)+10]?
jsdalton

3
@jsdalton: Chẳng phải nhà điều hành modulo sẽ tốt hơn sao? $((RANDOM % 90 + 10))Kiểm tra:for i in {0..9999}; do echo $((RANDOM % 90 + 10)); done | sort | uniq -c
geon

5
Trên nhiều hệ thống cron không sử dụng bash theo mặc định vì nó có thể là tốt hơn để tránh những bashism $RANDOM: sleep $(( $(od -N1 -tuC -An /dev/urandom) \% 90 ))m.
pabouk

9
Đảm bảo rằng bạn crontabđang sử dụng bashtrước khi sử dụng $RANDOM. Nếu bạn có vixie-cron(dường như là trường hợp của tôi trên Ubuntu), thì bạn có thể thêm SHELL=/bin/bashvào đầu trang. Có rất nhiều lựa chọn thay thế cho các phiên bản cron khác tại đây: superuser.com/a/264541/260350
DaAwesomeP

1
Khi tôi sử dụng gợi ý đầu tiên ở trên, tôi nhận được crontab: errors in crontab file, can't install. Do you want to retry the same edit?sự giúp đỡ
Seano 13/09/15

71

Vì vậy, tôi đang sử dụng phần sau để chạy lệnh từ 1AM đến 330AM

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

Điều đó đã được chăm sóc các nhu cầu ngẫu nhiên của tôi cho tôi. Đó là 9000 giây == 150 phút == 2,5 giờ


8
:: MindBLOWN :: một nơi khó hiểu khác để sử dụng một chút perl.
Mark Carpenter Jr

Đây chắc chắn là câu trả lời rõ ràng nhất
Enrico Detoma

21

Cron cung cấp một RANDOM_DELAYbiến. Xem crontab(5)chi tiết.

Biến RANDOM_DELAY cho phép trì hoãn việc khởi động công việc theo số phút ngẫu nhiên với giới hạn trên do biến chỉ định.

Điều này thường thấy trong các anacroncông việc, nhưng cũng có thể hữu ích trong a crontab.

Bạn có thể cần phải cẩn thận với điều này nếu bạn có một số công việc chạy ở mức độ chi tiết tốt (phút) và những công việc khác thì thô.


Tôi rất thích sử dụng biến RANDOM_DELAY, nhưng không thể tìm thấy bất kỳ gợi ý nào trong trang của crontab (5) trên Ubuntu 14.04.4 LTS.
Exocom

Thật không may. Tôi tự hỏi nếu nó không được hỗ trợ ở đó. Tôi thấy nó được ghi lại trong trang đó trên Centos 7 và Arch Linux.
Micah Elliott

9
điều này có vẻ giống như câu trả lời chính xác nhưng bạn có thể đặt một ví dụ?
chovy

14
Xin lưu ý rằng nó RANDOM_DELAYđược thiết lập một lần và không đổi trong toàn bộ thời gian chạy của daemon.
Maciej Swic

5
Các RANDOM_DELAYlá cờ là tính năng của cronie-crond trong khi Ubuntu vẻ là đang chạy vixie-cronmà thiếu lá cờ này.
kravietz

7

Suy nghĩ đầu tiên của tôi là tạo ra một công việc cron khởi chạy 20 công việc được lên lịch ngẫu nhiên. Các attiện ích (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) được sử dụng để thực hiện các lệnh tại thời gian nhất định.


Ví dụ về việc sử dụng at là ở đây: stackoverflow.com/a/6136145/803174
Kangur

6

Tôi đã kết thúc sử dụng sleep $(( 1$(date +%N) % 60 )) ; dostuffs(tương thích với bash & sh)

Tiền tố 1 là buộc NON cơ số 8 diễn giải ngày +% N (ví dụ: 00551454)

Đừng quên thoát% bằng cách sử dụng \% trong tệp crontab

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

2
Nếu ai đó thắc mắc, giống như tôi:% N cung cấp các nano hiện tại, nhưng một số trang nam thiếu thông tin về nó. Đây là một giải pháp rất thông minh cho những người chỉ cần "một số ngẫu nhiên" dễ dàng cho mỗi lệnh.
Thorsten Schöning

Ngoài những cảnh báo đã được đề cập ở những nơi khác, điều này sẽ chỉ hoạt động nếu bạn có GNU date(điều này có thể bạn thực hiện trên hầu hết các Linux, nhưng không phải trên Busybox, MacOS tiêu chuẩn hoặc nhiều nền tảng khác có nguồn gốc từ BSD).
tripleee

4

Giải pháp của al-x không hoạt động đối với tôi vì các lệnh crontab không được thực hiện trong bash nhưng trong sh tôi đoán. Công việc là gì:

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

Tôi đã thử mọi cách và nó vẫn không hiệu quả với tôi. Bạn đăng bài giải thích tại sao, cảm ơn!
marlar

$[ ... ]là cú pháp không được chấp nhận kể từ waaaay trở lại; đối với bất kỳ thứ gì từ thiên niên kỷ này, bạn sẽ thích $((RANDOM\%90))mcú pháp tương thích với POSIX (nhưng tất nhiên RANDOMvẫn chỉ là Bash).
tripleee

1

at -f [file] [timespec]

hoặc là

echo [command] | at [timespec]

hoặc là

at [timespec]... và đặc điểm kỹ thuật tương tác như scriptghi âm của.

Chỉ huy

Lúc chạy văn bản cung cấp trên stdin hoặc trong tệp được chỉ định bởi -f [file].

Timespec

Đây là [timespec] ngữ pháp . Nó có thể là một cái gì đó như:

  • Thời gian 24 giờ là 4 chữ số int, ví dụ như 0100, 2359,1620
  • now + 10 minutes
  • 2071-05-31 - 5 hours 12 minutes UTC

Nếu bạn chỉ định rõ ràng múi giờ, một số phiên bản của timepec có thể chỉ cho phép UTCđối số múi giờ tùy chọn.

Thí dụ

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

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

Hãy dùng thử ...

Bạn có thể kiểm tra phân tích cú pháp bash bằng cách chờ xử lý trước echovà thoát khỏi |(đường ống).

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

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

Để xem các công việc đã lên lịch, sử dụng atqvà nội dung công việc (môi trường, thiết lập và lệnh / script) với at -c [jobid].

Ghi chú

Hệ thống là một phần của cron và dấu nhắc tương tác thực sự nắm bắt toàn bộ trạng thái hiện tại của trình bao, vì vậy bạn có thể chạy các lệnh mà không cần chỉ định đường dẫn tuyệt đối.


0

Đối với những người đã truy cập vào googled ở đây:

Nếu bạn đang sử dụng anacron (máy tính để bàn và máy tính xách tay Ubuntu) thì bạn có thể chỉnh sửa

/etc/anacrontab

và thêm vào

RANDOM_DELAY=XX 

Trong đó XX là số phút bạn muốn trì hoãn công việc cơ bản.

Anacron giống như cron nhưng nó không mong đợi máy tính của bạn ở dạng 24x7 (như máy tính xách tay của chúng tôi) và sẽ chạy các tập lệnh mà nó đã bỏ lỡ do hệ thống bị lỗi.


0

Bạn có thể thử với ví dụ này để sử dụng thời gian ngẫu nhiên trước khi thực hiện lệnh:

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

Còn việc tạo script viết lại crontab mỗi ngày thì sao?

  1. Đọc cây trồng hiện tại (A)
  2. Chọn thời gian ngẫu nhiên (B)
  3. Viết lại các đường cắt trước (A), thêm các đường cắt ngẫu nhiên mới (B)
  4. Đảm bảo thêm vào cron để chạy tập lệnh này ngay từ đầu.

2
Đừng phá vỡ hệ thống danh tiếng bằng cách đăng nhận xét làm câu trả lời. Tuy nhiên, bình luận của bạn trông đủ tốt để thực sự một câu trả lời. Tôi khuyên bạn nên xóa " Tôi không có đại diện để thêm nhận xét, nhưng ".
Ted Lyngmo

1
Tôi vừa xem lại câu trả lời này và bỏ lỡ phần mà bạn đang đặt câu hỏi ngược lại ở cuối (phần tôi làm việc cẩu thả). Đừng đặt câu hỏi trong câu trả lời. Đăng câu hỏi của riêng bạn cho những câu hỏi bạn có. Tôi đã biến nửa câu hỏi của bạn thành một thứ gì đó có thể chuyển cho câu trả lời.
Ted Lyngmo

1
Hiểu rồi! Cám ơn. Lần sau tôi sẽ cẩn thận hơn, không có ý xấu.
mellofellow

1
Tôi chắc rằng bạn không có ý định xấu và bạn không cần phải quá cẩn thận. Bạn đã vạch ra một giải pháp khả thi - và hơi vấp ngã khi kết thúc. Đừng lo lắng!
Ted Lyngmo

0

Tôi nhận ra đó là một chuỗi cũ hơn, nhưng tôi muốn thêm một thứ liên quan đến giá trị ngẫu nhiên mà tôi sử dụng nhiều. Thay vì sử dụng biến $ RANDOM với phạm vi cố định và giới hạn, tôi thường tạo các giá trị ngẫu nhiên phạm vi tùy ý trong trình bao với

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

vì vậy bạn có thể làm, chẳng hạn như

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

và khắc phục một số hạn chế đã được thảo luận trong chủ đề này.


1
Chào mừng đến với SO. Chà, chủ đề cũ hay không, điều này đã gửi tôi đến ~$info ddvà tôi có thể hiểu những gì đang xảy ra ở phía bên trái của |, nhưng không thể hiểu được phía bên phải. Vì vậy, đối với tôi và những người khác quan tâm đến việc overcoming some restrictionstạo ra giá trị ngẫu nhiên, tại sao không dành một chút thời gian để giải thích RHS và đưa ra một quảng cáo mạnh mẽ hơn để sử dụng phương pháp của bạn. Sự giải thích sâu sắc vừa làm cho mọi người thoải mái với quy trình bạn đề xuất và lợi ích của nó Cảm ơn.
Chris

À được rồi. od aka "kết xuất bát phân" lấy một tệp hoặc stdin và kết xuất dữ liệu nhị phân ở dạng con người có thể đọc được. Chúng tôi muốn số của chúng tôi được hiển thị dưới dạng số thập phân không dấu (-t u4) và không muốn chỉ mục địa chỉ (-A không có). -N4 là thừa vì chúng ta chỉ lấy 4 byte, nhưng cũng không ảnh hưởng gì. Tôi hy vọng điều này giải thích nó ...
MLP
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.