Làm thế nào tôi có thể bảo cron chạy lệnh mỗi ngày (lẻ / chẵn)


45

Khi định cấu hình cron để chạy lệnh mỗi ngày bằng cách sử dụng trường "Ngày của tháng", như vậy:

1 22 */2 * * COMMAND

nó chạy mỗi lần trong ngày là tháng lẻ: 1,3,5,7,9, v.v.

Làm cách nào tôi có thể định cấu hình cron để chạy vào các ngày trong tháng thậm chí là 2,6,8,10 và cứ thế (mà không chỉ định theo nghĩa đen, điều này có vấn đề vì mỗi tháng có số ngày khác nhau trong tháng)?

Câu trả lời:


60

Cú pháp bạn đã thử thực sự mơ hồ. Tùy thuộc vào số ngày trong tháng, một số tháng sẽ chạy vào những ngày lẻ và một số ngày chẵn. Điều này là do cách tính toán sẽ lấy tổng số tích cực và chia chúng ra. Bạn có thể vượt quá hành vi can đảm này bằng cách chỉ định thủ công phạm vi ngày và sử dụng số ngày lẻ hoặc chẵn. Vì các tập lệnh ngày chẵn sẽ không bao giờ chạy vào ngày thứ 31 của các tháng dài hơn, bạn không mất bất cứ thứ gì sử dụng 30 ngày làm cơ sở cho các ngày chẵn và bằng cách chỉ định cụ thể để phân chia nó như thể có 31 ngày bạn có thể buộc lẻ -Thực hiện ngày.

Cú pháp sẽ như thế này:

# Will only run on odd days:
0 0 1-31/2 * * command

# Will only run on even days:
0 0 2-30/2 * * command

Mối quan tâm của bạn về những tháng không có cùng số ngày không quan trọng ở đây vì không có tháng nào có nhiều ngày hơn thế này và đối với tháng hai nghèo, phạm vi ngày sẽ không bao giờ khớp với ngày hoặc hai ngày trước, nhưng sẽ không có hại gì nó được liệt kê.

'Gotcha' duy nhất cho phương pháp này là nếu bạn đang ở trong một chu kỳ ngày lẻ, sau các tháng với 31 ngày, lệnh của bạn cũng sẽ chạy vào ngày đầu tiên của tháng. Tương tự như vậy nếu bạn buộc một chu kỳ chẵn, mỗi năm nhuận sẽ gây ra một chu kỳ ba ngày và cuối tháng Hai. Bạn không thể thực sự hiểu được rằng bất kỳ mô hình thông thường nào của "mọi ngày" không phải luôn luôn rơi vào các ngày chẵn hoặc lẻ trong mỗi tháng và bất kỳ cách nào bạn ép buộc điều này, bạn sẽ có thêm một lần chạy hoặc bị bỏ lỡ giữa tháng với số ngày không phù hợp


1
Cảm ơn, nhưng điều gì sẽ xảy ra vào những tháng như tháng hai mà bạn chỉ có 28 ngày? Ngôi sao thực sự quan tâm đến điều đó - nhưng thực sự mơ hồ.
freddie

3
@freddie: Xem câu trả lời đã được chỉnh sửa của tôi ... nhưng đó không phải là vấn đề vì ngoài phạm vi giá trị sẽ bị bỏ qua, sẽ không có gì xảy ra vào ngày 30 hoặc 31 tháng 2. Không bao giờ. Bạn có thể chỉ định thủ công với một danh sách như thế 0,2,4...,30,32,34và nó sẽ không thành vấn đề, các giá trị ngoài phạm vi sẽ không bao giờ được khớp.
Caleb

1
Cảm ơn! Tôi hiểu, cảm ơn bạn cho câu trả lời thông tin!
freddie

3
Trên máy chủ Ubuntu 8.04, có vẻ như cú pháp sử dụng số 0 trong ngày là không hợp lệ (ngày xấu trong tháng). Tuy nhiên, cú pháp sau đây được chấp nhận:0 0 2-30/2 * * command

1
Fedora và RHEL 5,6,7 cũng không thích 0 như một ngày trong tháng. Như user 31053 đã chỉ ra: 0 0 2-30/2 * * commandhoạt động như mong đợi.
NoelProf

2

Tôi nghĩ rằng một khả năng đang sử dụng ngày trong năm, như thế này:

# for odd days
test $(((`date +%j` % 2))) != 0 && command

# for even days
test $(((`date +%j` % 2))) == 0 && command

Nó được thử nghiệm cho các hệ thống Unix và Linux.


Tôi thích câu trả lời này vì nó bỏ qua vấn đề với số ngày lẻ với một số tháng. Dù sao, tôi đề nghị ký hiệu đô la thay vì backticks:test $(($(date +%j) % 2)) == 0 && command
caligari

Tôi đã xem xét rằng% j không phải là ngày Julian, vì vậy mã tốt nhất tránh chuyển đổi năm mới phải được tính bằng giây:test $(($(date +%s) / 86400 % 2)) == 0 && command
caligari

Cảm ơn các ý kiến! Đề xuất của chúng tôi làm việc cho chúng tôi như một nét duyên dáng. Chúng tôi đã sử dụng lược đồ đó để chạy các crons hàng ngày trên các nút máy chủ khác nhau, tất cả chúng đều chia sẻ cùng một crontab, nhưng tập lệnh chỉ cho phép chạy tập lệnh trên một trong số chúng. Tuy nhiên, nếu chúng tôi cần làm cho nó cụ thể hơn, chúng tôi sẽ xem xét đề xuất của bạn. Cảm ơn!!!
Jordi

1

Hãy kiểm tra mỗi ngày nếu đó là "khác" :-) ( bcyêu cầu chương trình)

0 0 * * * test $(echo `date +%s` / 86400 % 2 == 0 |bc) -eq 0 && command

(Tôi không chắc mã xuất hiện chính xác. Phần date +%snằm giữa các dấu nháy ngược.)


Điều này sẽ chạy mỗi ngày nhưng không trả lời câu hỏi! Nó vẫn sẽ chạy đôi khi vào những ngày lẻ đôi khi vào những ngày chẵn tùy theo tháng. Điều này có kết quả tương tự như mã trong câu hỏi, bạn chỉ đang đi đến kết quả bằng cách làm toán của riêng bạn trong vài giây kể từ kỷ nguyên. Điều này chạy vào các ngày chẵn kể từ kỷ nguyên nhưng không phải vào các ngày chẵn trong lịch của chúng tôi.
Caleb

1

Nói chung, tôi sẽ chạy nó mỗi ngày và có kịch bản sử dụng logic để xác định xem nó có nên chạy hôm nay không.

Tạo một tệp trạng thái đơn giản cho biết khi chạy lần cuối và sau đó kết hợp sẽ hoạt động rất dễ dàng.

Nếu nó cần được chạy qua các nguồn khác nhau, làm cho nó phụ thuộc vào đối số.

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.