Chạy một công việc định kỳ vào thứ Hai đầu tiên hàng tháng?


32

Tôi muốn điều hành một công việc từ cron vào lúc 8h30 vào thứ Hai đầu tiên hàng tháng. Trang Wikipedia cron nói

Mặc dù thông thường công việc được thực thi khi tất cả các trường đặc tả thời gian / ngày khớp với thời gian và ngày hiện tại, có một ngoại lệ: nếu cả "ngày trong tháng" và "ngày trong tuần" bị hạn chế (không phải "*"), thì một trong hai trường "ngày trong tháng" (3) hoặc trường "ngày trong tuần" (5) phải khớp với ngày hiện tại.

(nhấn mạnh của tôi)

Điều đó có nghĩa là tôi không thể làm thứ Hai đầu tiên của tháng, tôi chỉ có thể làm ngày đầu tiên (hoặc bất cứ điều gì) trong tháng? Tôi không thể nghĩ ra một cách làm tròn nó.


slhck - nghe có vẻ là một giải pháp tốt - bạn có phiền mở rộng nó thành một câu trả lời với mã đầy đủ không? sau đó tôi sẽ đánh dấu nó là chính xác :)
Max Williams

Câu trả lời:


39

Bạn có thể đặt điều kiện vào lệnh crontab thực tế:

[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"

Bây giờ, nếu điều kiện này là đúng vào một trong bảy ngày đầu tiên trong tháng, bạn có ngày thứ Hai đầu tiên. Lưu ý rằng trong crontab, cú pháp phần trăm cần phải được thoát mặc dù:

0   12  1-7 *   *   [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"

Thay thế echolệnh bằng lệnh thực tế bạn muốn chạy. Tôi cũng tìm thấy một cách tiếp cận tương tự .


Thật ra, slhck, tôi đã nói quá sớm - điều này không hoạt động trong crontab của tôi: nó dường như có vấn đề với bài kiểm tra ngày vì một số lý do. Điều này hoạt động trong dòng lệnh [ "$(date '+%a')" = "Mon" ] && echo "It's Monday"cũng như [ $(date '+%a') = "Mon" ] && echo "It's Monday" Nhưng, trong crontab dường như thất bại ở thử nghiệm này. Tôi cũng không thể nhận được bất kỳ phản hồi hữu ích nào từ cron: Tôi đang cố gắng [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1để ghi lại bất kỳ đầu ra lỗi nào vào nhật ký nhưng điều đó cũng không hoạt động: /
Max Williams

Hừm. Bạn có thể kiểm tra xem dateđầu ra có đúng không? Ví dụ: chỉ cần để một cronlệnh chạy kết xuất này thành một tệp: date '+%a' > ~/datetest 2>&1- sau đó kiểm tra xem điều đó có dẫn đến chuỗi đúng để so sánh với không.
slhck

1
Tôi đã tìm thấy vấn đề - phần trăm trong +%athoát cần thiết khi nó ở trong crontab, tức là dòng cần thiết là : [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". Nếu bạn có thể cập nhật câu trả lời của mình với điều đó sẽ hữu ích cho những độc giả tương lai :) Cảm ơn một lần nữa - tối đa
Max Williams

Ồ, bây giờ tôi hiểu tại sao. Vui mừng bây giờ nó hoạt động, cảm ơn vì đã thử nó!
slhck

14

Tôi có một máy tính với ngôn ngữ địa phương bằng tiếng Tây Ban Nha, vì vậy, cách tiếp cận này không hiệu quả với tôi vì mon thay đổi thành lun

Các ngôn ngữ khác cũng sẽ thất bại, vì vậy, tôi đã thực hiện một biến thể nhỏ trên câu trả lời được chấp nhận để loại bỏ rào cản ngôn ngữ:

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"

+1 ¡Muy bien, señor!
JakeGould

1
Gracias ¡Pura vida! ; D
cumanacr

Đây phải là câu trả lời được chấp nhận. Tôi có một địa phương Hà Lan cũng sử dụng các tên khác nhau cho các ngày trong tuần. Và sử dụng số cũng cảm thấy sạch hơn so với việc so sánh các chuỗi để xác định ngày trong tuần.
0ne_Up

7

Tôi thấy dễ dàng hơn khi không cần phải xử lý số ngày.

Chạy thứ hai đầu tiên của tháng:

0 2 * * 1 [ `date '+\%m'` == `date '+\%m' -d "1 week ago"` ] || /path/to/command

tức là nếu tháng 1 tuần trước không giống với tháng hiện tại thì chúng ta đang ở ngày 1 (= thứ hai) của tháng.

Tương tự, cho thứ Sáu thứ ba

0 2 * * 6 [ `date '+\%m'` == `date '+\%m' -d "3 weeks ago"` ] || /path/to/command

tức là nếu tháng 3 tuần trước khác với tháng hiện tại thì chúng ta đang ở ngày thứ 3 6 (= thứ sáu) của tháng


Ngày 6 trong tuần là thứ bảy không phải thứ sáu.
Robert

4

Tôi đã lên lịch cho một công việc để chạy vào thứ Hai thứ 4 hàng tháng vào lúc 4:00 chiều như sau:

0 16 22-28 * Mon [ "$(date '+\%a')" == "Mon" ] && touch /home/me/FourthMonOfMonth.txt

1

Theo như tôi biết thì KHÔNG thể chỉ sử dụng crontab, tuy nhiên người ta có thể sử dụng chức năng bao bọc để chọn ngày chính xác từ mục nhập contab "bảy ngày đầu tiên của tháng"; thấy điều này từ mục.

Kịch bản bao bọc sẽ là

#! /usr/bin/ksh
day=$(date +%d)
if ((day <= 7)) ; then
   exec somecommand
fi
exit 1

và bạn sẽ cần chạy nó (giả sử nó được gọi là Wrapper.sh và có sẵn trên toàn cầu) bằng cách sử dụng mục crontab

0 0 * * 1 wrapper.sh

cảm ơn elemaki Tôi đã nghĩ về một giải pháp tương tự bằng cách sử dụng một số mã bổ sung bên trong tác vụ được chạy, để nó kiểm tra xem đó có phải là thứ hai đầu tiên của tháng trong tập lệnh hay không, và sau đó gọi nó vào thứ hai hàng tuần trong crontab. Đó là một kịch bản ruby ​​để dễ dàng kiểm tra ngày trong tuần. Nhưng tôi đã hy vọng sẽ chỉ có một crontab.
Max Williams

1

Trên Solaris 10 tôi phải định dạng điều kiện như sau:

[ `date +\%a` = "Sat" ] && echo "It's Saturday"

1

Bạn có thể thử chạy cronjob trong bảy ngày đầu tiên của tháng và chỉ để nó thực hiện vào Thứ Hai.

30 8 * * 1 [`date +\%d` -le 07] && <job>

Ở trên nên làm việc cho bạn.


+1 thành công hơn đạt được khẩu phần sau đó để chạy trong tuần đầu tiên và kiểm tra vào thứ Hai. :-)
xmedeko

1

Tôi khuyên bạn nên sử dụng

"$(/bin/date '+%\w')" = "1"

thay vì

"$(date '+\%a')" = "Mon"

để tránh vấn đề bản địa.


0

Tôi đã thực hiện một giải pháp chung cho loại vấn đề này, nó hoạt động cho lần đầu tiên, thứ hai, thứ ba ..... ngày cuối tuần trong tháng.

Bạn có thể sử dụng nó như thế này:

30 06 * * Mon run-if-today 1 "Mon" && echo "First Monday"
30 06 * * Thu run-if-today 3 "Thu" && echo "Third Thursday"
30 06 * * Sun run-if-today L "Sun" && echo "Last Sunday"

Kịch bản run-if-today kiểm tra cả ngày trong tuần và phạm vi ngày trong tuần mong muốn, nếu cả hai khớp nhau thì nó trả về 0, nếu không thì 1.

Kiểm tra mã ở đây. https://github.com/xr09/cron-last- chủ nhật


0

Tôi tin rằng điều này giải quyết vấn đề một cách thanh lịch hơn:

30 8 1-7 * 1 /run/your/job.sh

1
Đừng! : "Nếu cả hai trường bị hạn chế (nghĩa là không *), lệnh sẽ được chạy khi một trong hai trường khớp với thời gian hiện tại."
symcbean

Cũng vào tháng 2 (kết thúc vào ngày 28), nó sẽ không được chạy 4 năm một lần.
igrac817

"Hoặc" có nghĩa là bất kỳ trong số họ, không phải "cả hai". cái này sẽ chạy mỗi ngày trong 7 ngày đầu tiên của tháng.
trừ

Hàng này sẽ chạy một lệnh vào ngày đầu tiên đến thứ bảy mỗi tháng, cũng như vào mỗi thứ Hai
Tomasz Jakub Rup

0

Vì tôi diễn giải các câu lệnh cron của mình bằng php và js, tôi không thể sử dụng bash. Cuối cùng tôi phát hiện ra rằng nó trong thực tế có thể chỉ với cron:

0 30 8 * 1/1 MON#1

Hy vọng điều này sẽ giúp người khác. Bất kể, tôi muốn tất cả các bạn một ngày đẹp trời. :-)


Đây không phải là cron, nó có thể là thạch anh
sivann

-1
0 9 1-7 * 1 * 

Điều này sẽ làm việc cho mỗi thứ hai hàng tháng.


Một câu trả lời đã được chấp nhận, là câu trả lời của bạn tốt hơn, khác biệt hay hữu ích hơn trên phiên bản mới hơn, v.v.
mic84
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.