ทำงาน cron ในวันจันทร์แรกของทุกเดือนหรือไม่


32

ฉันต้องการทำงานจาก cron เวลา 8.30 น. ในวันจันทร์แรกของทุกเดือน หน้า cron Wikipedia พูดว่า

ในขณะที่ตามปกติงานจะดำเนินการเมื่อเวลา / วันเขตสเปคทั้งหมดตรงกับวันและเวลาปัจจุบันมีหนึ่งข้อยกเว้น: ถ้าทั้งสอง "วันของเดือน" และ "วันของสัปดาห์" ถูก จำกัด (ไม่ใช่ "*") จากนั้นทั้งสองฟิลด์ "วันของเดือน" (3) หรือฟิลด์ "วันของสัปดาห์" (5) จะต้องตรงกับวันปัจจุบัน

(ความสำคัญของฉัน)

หมายความว่าฉันไม่สามารถทำวันจันทร์แรกของเดือนฉันสามารถทำวันแรกของเดือน (หรืออะไรก็ได้)? ฉันไม่สามารถคิดวิธีรอบมัน


slhck - ฟังดูเหมือนเป็นวิธีแก้ปัญหาที่ดี - คุณจะขยายความในคำตอบด้วยรหัสเต็มหรือไม่? แล้วฉันจะทำเครื่องหมายว่าถูกต้อง :)
แม็กซ์วิลเลียมส์

คำตอบ:


39

คุณสามารถใส่เงื่อนไขลงในคำสั่ง crontab จริง:

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

ทีนี้ถ้าเงื่อนไขนี้เป็นจริงในหนึ่งในเจ็ดวันแรกของเดือนคุณมีวันจันทร์แรก โปรดทราบว่าใน crontab ไวยากรณ์เปอร์เซ็นต์ต้องได้รับการยกเว้นว่า:

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

แทนที่echoคำสั่งด้วยคำสั่งจริงที่คุณต้องการเรียกใช้ ฉันพบวิธีการที่คล้ายกันด้วย


ที่จริงแล้วฉันพูดเร็วเกินไป - นี่ไม่ได้ทำงานใน crontab ของฉัน: ดูเหมือนว่าจะมีปัญหากับการทดสอบวันที่ด้วยเหตุผลบางอย่าง มันใช้งานได้ในบรรทัดคำสั่ง[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"เหมือน[ $(date '+%a') = "Mon" ] && echo "It's Monday" แต่ใน crontab ดูเหมือนว่าจะล้มเหลวในการทดสอบนี้ ฉันไม่สามารถรับข้อเสนอแนะที่เป็นประโยชน์จาก cron เช่นกัน: ฉันกำลังพยายาม[ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1จับข้อผิดพลาดเอาท์พุทใด ๆ ลงในบันทึก แต่ก็ไม่ได้ผลเช่นกัน: /
Max Williams

ฮึ่ม คุณสามารถตรวจสอบว่าdateเอาต์พุตถูกต้องหรือไม่? ตัวอย่างเช่นเพียงแค่ให้cronคำสั่งรันผลลัพธ์นี้ไปยังไฟล์: date '+%a' > ~/datetest 2>&1- จากนั้นตรวจสอบว่าผลลัพธ์นั้นเป็นสตริงที่เหมาะสมเพื่อเปรียบเทียบกับหรือไม่
slhck

1
ผมพบว่าปัญหาที่เกิดขึ้นเป็นร้อยละ - ใน+%aที่จำเป็นในการหลบหนีเมื่อมันอยู่ใน crontab [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"คือเส้นที่จำเป็นในการเป็นแบบนี้: หากคุณสามารถอัปเดตคำตอบของคุณโดยจะเป็นประโยชน์ต่อผู้อ่านในอนาคต :) ขอบคุณอีกครั้ง - สูงสุด
Max Williams

โอ้ตอนนี้ฉันเห็นว่าทำไม ดีใจที่มันใช้งานได้ในตอนนี้ขอบคุณที่ทดลองใช้!
slhck

14

ฉันมีคอมพิวเตอร์ที่มีโลแคลเป็นภาษาสเปนดังนั้นวิธีนี้ไม่ได้ผลสำหรับฉันเพราะจันทร์เปลี่ยนเป็นดวงจันทร์

ภาษาอื่น ๆ ก็จะล้มเหลวเช่นกันดังนั้นฉันจึงเปลี่ยนแปลงคำตอบที่ยอมรับได้เล็กน้อยซึ่งเป็นอุปสรรคต่อภาษา:

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

+1 uy Muy bien, señor!
JakeGould

1
Gracias ¡ Pura vida! ; D
cumanacr

นี่ควรเป็นคำตอบที่ยอมรับได้ ฉันมีภาษาดัทช์ซึ่งใช้ชื่อต่างกันในวันธรรมดา และการใช้ตัวเลขยังรู้สึกสะอาดกว่าการเปรียบเทียบสตริงเพื่อกำหนดวันในสัปดาห์
0ne_Up

7

ฉันพบว่าง่ายขึ้นเมื่อไม่จำเป็นต้องจัดการตัวเลขวัน

เรียกใช้วันจันทร์แรกของเดือน:

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

เช่นถ้าเดือน 1 สัปดาห์ที่แล้วไม่ตรงกับเดือนปัจจุบันเราจะอยู่ในวันที่ 1 1 (= วันจันทร์) ของเดือน

ในทำนองเดียวกันสำหรับวันศุกร์ที่สาม

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

เช่นถ้าเดือน 3 สัปดาห์ที่แล้วแตกต่างจากเดือนปัจจุบันเราอยู่ในวันที่ 3 6 (= วันศุกร์) ของเดือน


วันที่ 6 ของสัปดาห์คือวันเสาร์ไม่ใช่วันศุกร์
Robert

4

ฉันได้กำหนดเวลาให้ทำงานในวันจันทร์ที่ 4 ของทุกเดือนเวลา 16.00 น. ดังนี้:

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

1

เท่าที่ฉันรู้ว่ามันเป็นไปไม่ได้ที่จะใช้ crontab เพียงอย่างเดียว แต่เราสามารถใช้ฟังก์ชั่น wrapper เพื่อเลือกวันที่ถูกต้องจากรายการ "เจ็ดวันแรกของเดือน" ดูสิ่งนี้จากรายการ

สคริปต์ตัวตัดคำจะเป็น

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

และคุณจะต้องเรียกใช้ (สมมติว่ามันเรียกว่า wrapper.sh และมีอยู่ทั่วโลก) โดยใช้รายการ crontab

0 0 * * 1 wrapper.sh

ขอบคุณ elemaki ฉันคิดเกี่ยวกับวิธีแก้ปัญหาที่คล้ายกันโดยใช้โค้ดพิเศษบางอย่างในงานที่เรียกใช้เพื่อทดสอบว่ามันเป็นวันจันทร์แรกของเดือนในสคริปต์แล้วเรียกมันว่าทุกวันจันทร์ใน crontab มันเป็นสคริปต์ทับทิมดังนั้นจึงง่ายต่อการทดสอบวันที่สัปดาห์ แต่ฉันหวังว่าจะมี crontab แบบเดียวเท่านั้น
Max Williams

1

บน Solaris 10 ฉันต้องจัดรูปแบบเงื่อนไขดังนี้:

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

1

คุณสามารถลองใช้ cronjob ในช่วงเจ็ดวันแรกของเดือนและปล่อยให้มันรันในวันจันทร์เท่านั้น

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

ข้างต้นควรทำงานให้คุณ


เพิ่มอีกหนึ่งการประสบความสำเร็จจากการปันส่วนสำหรับสัปดาห์แรกและตรวจสอบวันจันทร์ :-)
xmedeko


0

ฉันได้แก้ปัญหาทั่วไปสำหรับปัญหาแบบนี้มันทำงานได้ในวันที่หนึ่งที่สองที่สาม ..... วันสุดท้ายของเดือน

คุณสามารถใช้สิ่งนี้:

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"

สคริปต์ที่เรียกใช้ถ้าวันนี้ตรวจสอบทั้งวันทำงานและช่วงวันที่สัปดาห์ที่ต้องการถ้าทั้งคู่ตรงกันแล้วมันจะส่งกลับ 0 หรือมิฉะนั้น 1

ตรวจสอบรหัสที่นี่ https://github.com/xr09/cron-last-sunday


0

ฉันเชื่อว่านี่จะช่วยแก้ปัญหาได้อย่างสวยงามยิ่งขึ้น:

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

1
Doh! : "หากทั้งสองเขตข้อมูลถูก จำกัด (เช่นไม่ใช่ *) คำสั่งจะทำงานเมื่อทั้งสองเขตข้อมูลตรงกับเวลาปัจจุบัน"
symcbean

นอกจากนี้ในเดือนกุมภาพันธ์ (อันที่สิ้นสุดวันที่ 28) จะไม่ถูกเรียกใช้ทุก 4 ปี
igraczech

"อย่างใดอย่างหนึ่ง" หมายถึงใด ๆ ของพวกเขาไม่ได้ "ทั้ง" สิ่งนี้จะทำงานทุกวันสำหรับ 7 วันแรกของเดือน
ลบ

แถวนี้จะเรียกใช้คำสั่งในวันที่หนึ่งถึงวันที่เจ็ดของแต่ละเดือนเช่นเดียวกับทุกวันจันทร์
Tomasz Jakub Rup

0

เนื่องจากฉันตีความคำสั่ง cron โดยใช้ php และ js ฉันจึงไม่สามารถใช้ bash ได้ ในที่สุดฉันก็พบว่ามันเป็นไปได้จริงด้วย cron เพียง:

0 30 8 * 1/1 MON#1

หวังว่านี่จะช่วยคนอื่นได้ ไม่ว่าฉันหวังว่าคุณจะเป็นวันที่สวยงาม :-)


นี่ไม่ใช่ cron มันอาจเป็น quartz
sivann

-1
0 9 1-7 * 1 * 

สิ่งนี้จะใช้ได้กับทุกวันจันทร์ของทุกเดือน


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