ฉันจะบอก cron ให้รันคำสั่งได้ทุกวัน ๆ (คี่ / คู่)


45

เมื่อกำหนดค่า cron ให้เรียกใช้คำสั่งทุกวันโดยใช้ฟิลด์ "วันเดือน" เช่น:

1 22 */2 * * COMMAND

มันทำงานทุกครั้งที่วันของเดือนคี่: 1,3,5,7,9 และอื่น ๆ

ฉันจะกำหนดค่า cron ให้ทำงานในวันของเดือนที่เป็นเช่น 2,6,8,10 เป็นต้นไปได้อย่างไร (โดยไม่ระบุตัวอักษรซึ่งเป็นปัญหาเนื่องจากทุกเดือนมีจำนวนวันแตกต่างกันในเดือน)

คำตอบ:


60

ไวยากรณ์ที่คุณลองใช้นั้นไม่ชัดเจนจริง ๆ ขึ้นอยู่กับจำนวนวันในเดือนบางเดือนจะทำงานในวันที่คี่และบางคู่ นี่เป็นเพราะวิธีการคำนวณนั้นใช้จำนวนรวมของความเป็นไปได้ทั้งหมดและหารมันขึ้นมา คุณสามารถขับพฤติกรรม strage-ish นี้ได้ด้วยการระบุช่วงวันด้วยตนเองและใช้จำนวนวันคี่หรือคู่ เนื่องจากแม้แต่สคริปต์วันจะไม่ทำงานในวันที่ 31 ของเดือนที่ยาวนานคุณไม่หลวมสิ่งใดโดยใช้ 30 วันเป็นฐานสำหรับวันคู่และโดยการระบุเฉพาะเพื่อแบ่งมันราวกับว่ามี 31 วันคุณสามารถบังคับคี่ การทำงานประจำวัน

ไวยากรณ์จะมีลักษณะเช่นนี้:

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

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

ความกังวลของคุณเกี่ยวกับเดือนที่ไม่มีจำนวนวันเท่ากันนั้นไม่สำคัญเพราะที่นี่ไม่มีเดือนมีจำนวนวันมากกว่านี้และสำหรับเดือนกุมภาพันธ์ที่ไม่ดีช่วงวันที่ไม่ตรงกับวันหรือสองวันสุดท้าย แต่จะไม่มีอันตรายใด ๆ มันอยู่ในรายการ

'gotcha' เพียงวิธีเดียวสำหรับวิธีนี้คือถ้าคุณอยู่ในวัฏจักรวันที่แปลกเดือนถัดไปที่มี 31 วันคำสั่งของคุณก็จะทำงานในวันแรกของเดือน ในทำนองเดียวกันถ้าคุณบังคับให้มีรอบสม่ำเสมอในแต่ละปีอธิกสุรทินจะทำให้เกิดหนึ่งรอบสามวันและสิ้นเดือนกุมภาพันธ์ คุณไม่สามารถหลีกเลี่ยงความจริงที่ว่ารูปแบบปกติของ "วันเว้นวัน" ไม่ได้มักจะตกอยู่ในวันคู่หรือคี่ในทุกเดือนและวิธีที่คุณบังคับให้คุณทำเช่นนี้คุณจะต้องวิ่งพิเศษหรือพลาดวิ่งระหว่าง เดือนที่มีการนับวันที่ผิดพลาด


1
ขอบคุณ แต่จะเกิดอะไรขึ้นในหลายเดือนเช่นกุมภาพันธ์ที่คุณมีเพียง 28 วัน? ดาวดวงนั้นดูแลจริง ๆ - แต่แน่นอนว่าคลุมเครือ
freddie

3
@freddie: ดูคำตอบที่แก้ไขแล้วของฉัน ... แต่มันไม่ใช่ปัญหาเพราะค่าที่อยู่นอกช่วงจะถูกเพิกเฉยไม่มีอะไรจะเกิดขึ้นในวันที่ 30 หรือ 31 กุมภาพันธ์ เคย คุณสามารถระบุด้วยรายการที่ต้องการได้ด้วยตนเอง0,2,4...,30,32,34และไม่สำคัญว่าค่านอกช่วงจะไม่ตรงกัน
Caleb

1
ขอบคุณ! ฉันเข้าใจขอบคุณสำหรับคำตอบที่ให้ข้อมูล!
freddie

3
บนเซิร์ฟเวอร์ Ubuntu 8.04 ดูเหมือนว่าไวยากรณ์ที่ใช้ศูนย์รายวันนั้นไม่ถูกต้อง (วันที่ไม่ดีของเดือน) อย่างไรก็ตามยอมรับไวยากรณ์ต่อไปนี้:0 0 2-30/2 * * command

1
Fedora และ RHEL 5,6,7 ก็ไม่ชอบ 0 เหมือนกันทุกวัน ตามที่ผู้ใช้ 31053 ชี้ให้เห็น: 0 0 2-30/2 * * commandทำงานตามที่คาดไว้
NoelProf

2

ฉันคิดว่ามีความเป็นไปได้ที่จะใช้วันของปีเช่นนี้

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

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

มันได้รับการทดสอบสำหรับระบบ Unix และ Linux


ฉันชอบคำตอบนี้เพราะข้ามปัญหากับจำนวนวันที่แปลกกับบางเดือน อย่างไรก็ตามฉันแนะนำให้ใช้สัญลักษณ์ดอลลาร์แทน backticks:test $(($(date +%j) % 2)) == 0 && command
caligari

ผมได้ตรวจสอบว่า j% ไม่ได้เป็นวันที่จูเลียนดังนั้นรหัสที่ดีที่สุดของการหลีกเลี่ยงการเปลี่ยนแปลงปีใหม่จะต้องคำนวณกับวินาทีtest $(($(date +%s) / 86400 % 2)) == 0 && command
Caligari

ขอบคุณสำหรับความคิดเห็น! ข้อเสนอของเราทำงานเพื่อเราอย่างมีเสน่ห์ เราใช้รูปแบบนั้นเพื่อเรียกใช้ crons ทุกวันบนโหนดเซิร์ฟเวอร์ที่ต่างกันทั้งหมดที่พวกเขาแบ่งปัน crontab เดียวกัน แต่สคริปต์อนุญาตให้เรียกใช้สคริปต์กับหนึ่งในนั้นเท่านั้น อย่างไรก็ตามหากเราต้องการทำให้เฉพาะเจาะจงมากขึ้นเราจะพิจารณาข้อเสนอของคุณ ขอบคุณ !!!
Jordi

1

ตรวจสอบทุกวันว่าเป็น "other" :-) ( bcต้องใช้โปรแกรม)

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

(ฉันไม่แน่ใจว่ารหัสปรากฏขึ้นอย่างถูกต้องdate +%sส่วนอยู่ระหว่างเครื่องหมายวรรคตอนด้านหลัง)


นี่จะทำงานทุกวัน แต่ไม่ตอบคำถาม! มันจะยังคงทำงานบางครั้งในวันที่แปลกบางครั้งในวันที่เท่ากันขึ้นอยู่กับเดือน สิ่งนี้มีผลลัพธ์เหมือนกับรหัสในคำถามคุณเพิ่งมาถึงผลลัพธ์ด้วยการทำคณิตศาสตร์ของคุณเองในไม่กี่วินาทีนับตั้งแต่ยุค สิ่งนี้จะทำงานในวันคู่ตั้งแต่ยุค แต่ไม่ใช่ในวันที่เท่ากันในปฏิทินของเรา
Caleb

1

โดยทั่วไปฉันจะรันทุกวันและให้สคริปต์ใช้ตรรกะในการพิจารณาว่าควรรันในวันนี้หรือไม่

การสร้างไฟล์บอกสถานะอย่างง่าย ๆ เมื่อใช้งานครั้งสุดท้ายจากนั้นการจับคู่จะทำงานได้อย่างง่ายดาย

หากจำเป็นต้องเรียกใช้ผ่านแหล่งต่าง ๆ ให้ขึ้นอยู่กับอาร์กิวเมนต์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.