ฉันต้องการสร้างงาน CRON ที่จะทำงานในวันสุดท้ายของทุกเดือน ฉันจะสร้างโดยใช้ cPanel
ขอความช่วยเหลือใด ๆ ขอบคุณ
ฉันต้องการสร้างงาน CRON ที่จะทำงานในวันสุดท้ายของทุกเดือน ฉันจะสร้างโดยใช้ cPanel
ขอความช่วยเหลือใด ๆ ขอบคุณ
คำตอบ:
อาจเป็นวิธีที่ง่ายที่สุดคือการทำงานสามอย่างแยกกัน:
55 23 30 4,6,9,11 * myjob.sh
55 23 31 1,3,5,7,8,10,12 * myjob.sh
55 23 28 2 * myjob.sh
ซึ่งจะดำเนินการในวันที่ 28 กุมภาพันธ์แม้ว่าจะเป็นปีอธิกสุรทินก็ตามดังนั้นหากเป็นปัญหาคุณจะต้องหาวิธีอื่น
อย่างไรก็ตามโดยปกติแล้วจะง่ายกว่าและถูกต้องมากในการทำงานโดยเร็วที่สุดในวันแรกของแต่ละเดือนโดยมีสิ่งต่อไปนี้:
0 0 1 * * myjob.sh
และแก้ไขสคริปต์เพื่อประมวลผลข้อมูลของเดือนก่อนหน้า
วิธีนี้จะช่วยขจัดความยุ่งยากที่คุณอาจพบในการหาว่าวันใดเป็นวันสุดท้ายของเดือนและยังช่วยให้มั่นใจได้ว่าข้อมูลทั้งหมดสำหรับเดือนนั้นจะพร้อมใช้งานโดยสมมติว่าคุณกำลังประมวลผลข้อมูล การวิ่งในเวลาห้านาทีถึงเที่ยงคืนของวันสุดท้ายของเดือนอาจทำให้คุณพลาดสิ่งที่เกิดขึ้นระหว่างนั้นถึงเที่ยงคืน
นี่เป็นวิธีปกติที่ต้องทำสำหรับงานสิ้นเดือนส่วนใหญ่
หากคุณยังคงจริงๆต้องการที่จะใช้มันในวันสุดท้ายของเดือนทางเลือกหนึ่งก็คือการตรวจสอบว่าในวันพรุ่งนี้เป็นครั้งแรก (ไม่ว่าจะเป็นส่วนหนึ่งของสคริปต์ของคุณหรือใน crontab เอง)
ดังนั้นสิ่งที่ชอบ:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
ควรจะเริ่มต้นที่ดีสมมติว่าคุณมีค่อนข้างฉลาดdate
โปรแกรม
หากdate
โปรแกรมของคุณยังไม่ก้าวหน้าพอที่จะระบุวันที่ที่สัมพันธ์กันได้คุณก็สามารถรวบรวมโปรแกรมง่ายๆเพื่อให้วันพรุ่งนี้ของเดือน (คุณไม่จำเป็นต้องมีพลังเต็มที่date
) เช่น:
#include <stdio.h>
#include <time.h>
int main (void) {
// Get today, somewhere around midday (no DST issues).
time_t noonish = time (0);
struct tm *localtm = localtime (&noonish);
localtm->tm_hour = 12;
// Add one day (86,400 seconds).
noonish = mktime (localtm) + 86400;
localtm = localtime (&noonish);
// Output just day of month.
printf ("%d\n", localtm->tm_mday);
return 0;
}
จากนั้นใช้ (สมมติว่าคุณเรียกมันว่าtomdom
"วันพรุ่งนี้ของเดือน"):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
แม้ว่าคุณอาจต้องการพิจารณาเพิ่มการตรวจสอบข้อผิดพลาดเนื่องจากทั้งสองอย่างtime()
และmktime()
สามารถส่งคืนได้-1
หากมีสิ่งผิดปกติเกิดขึ้น รหัสข้างต้นด้วยเหตุผลด้านความเรียบง่ายไม่ได้คำนึงถึงสิ่งนั้น
มีวิธีที่สั้นกว่าเล็กน้อยซึ่งสามารถใช้ได้คล้ายกับวิธีข้างต้น นั่นคือ:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
นอกจากนี้รายการ crontab สามารถอัปเดตเพื่อตรวจสอบเฉพาะในวันที่ 28 ถึง 31 เนื่องจากไม่มีจุดหมายที่จะเรียกใช้ในวันอื่น ๆ ของเดือน ซึ่งจะให้คุณ:
0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh
/bin/sh: -c: line 1: unexpected EOF while looking for matching ')'
ข้อผิดพลาดที่ผมได้รับคือ
[ $(date -d +1day +\%d) -eq 1 ] && run_job
posix
และวันที่ POSIXไม่รองรับ"-d +1day"
: - \ วิธีแก้ปัญหาที่ซับซ้อนกว่า (และน่าเกลียด) จะเป็น:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
ตั้งค่างาน cron เพื่อทำงานในวันแรกของเดือน จากนั้นเปลี่ยนนาฬิกาของระบบเป็นหนึ่งวันข้างหน้า
การปรับแก้โซลูชันของ paxdiablo ฉันทำงานในวันที่ 28 และ 29 กุมภาพันธ์ ข้อมูลจากวันที่ 29 เขียนทับวันที่ 28
# min hr date month dow
55 23 31 1,3,5,7,8,10,12 * /path/monthly_copy_data.sh
55 23 30 4,6,9,11 * /path/monthly_copy_data.sh
55 23 28,29 2 * /path/monthly_copy_data.sh
,29
.
55 23 28 2
?
คุณสามารถตั้งค่างาน cron ให้ทำงานได้ทุกวันของเดือนและเรียกใช้เชลล์สคริปต์ดังต่อไปนี้ สคริปต์นี้ระบุว่าจำนวนวันพรุ่งนี้น้อยกว่าวันนี้หรือไม่ (เช่นถ้าพรุ่งนี้เป็นเดือนใหม่) จากนั้นทำสิ่งที่คุณต้องการ
TODAY=`date +%d`
TOMORROW=`date +%d -d "1 day"`
# See if tomorrow's day is less than today's
if [ $TOMORROW -lt $TODAY ]; then
echo "This is the last day of the month"
# Do stuff...
fi
สำหรับวิธีที่ปลอดภัยยิ่งขึ้นใน crontab ที่ใช้โซลูชัน @Indie (ใช้พา ธ สัมบูรณ์ไปที่date
+ ใช้$()
ไม่ได้กับระบบ crontab ทั้งหมด):
0 23 28-31 * * [ `/bin/date -d +1day +\%d` -eq 1 ] && myscript.sh
การใช้งาน cron บางอย่างสนับสนุนค่าสถานะ "L" เพื่อแสดงวันสุดท้ายของเดือน
หากคุณโชคดีที่ได้ใช้หนึ่งในการใช้งานเหล่านี้ทำได้ง่ายๆดังนี้:
0 55 23 L * ?
ซึ่งจะเริ่มในเวลา 23:55 น. ของทุกวันสุดท้ายของเดือน
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
#########################################################
# Memory Aid
# environment HOME=$HOME SHELL=$SHELL LOGNAME=$LOGNAME PATH=$PATH
#########################################################
#
# string meaning
# ------ -------
# @reboot Run once, at startup.
# @yearly Run once a year, "0 0 1 1 *".
# @annually (same as @yearly)
# @monthly Run once a month, "0 0 1 * *".
# @weekly Run once a week, "0 0 * * 0".
# @daily Run once a day, "0 0 * * *".
# @midnight (same as @daily)
# @hourly Run once an hour, "0 * * * *".
#mm hh Mday Mon Dow CMD # minute, hour, month-day month DayofW CMD
#........................................Minute of the hour
#| .................................Hour in the day (0..23)
#| | .........................Day of month, 1..31 (mon,tue,wed)
#| | | .................Month (1.12) Jan, Feb.. Dec
#| | | | ........day of the week 0-6 7==0
#| | | | | |command to be executed
#V V V V V V
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "Tomorrow is the first today now is `date`" >> ~/message
1 0 1 * * rm -f ~/message
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "HOME=$HOME LOGNAME=$LOGNAME SHELL = $SHELL PATH=$PATH"
สำหรับการใช้งาน AWS Cloudwatch cron (การตั้งเวลา Lambdas ฯลฯ .. ) สิ่งนี้ใช้ได้:
55 23 L * ? *
วิ่งเวลา 23:55 น. ของวันสุดท้ายของแต่ละเดือน
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
ดูคำถามที่เกี่ยวข้องในฟอรัม unix.com
คุณสามารถเชื่อมต่อคำตอบทั้งหมดใน cron บรรทัดเดียวและใช้date
คำสั่งเท่านั้น
เพียงตรวจสอบความแตกต่างระหว่างวันของเดือนซึ่งเป็นวันนี้และจะเป็นวันพรุ่งนี้:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
หากความแตกต่างเหล่านี้ต่ำกว่า 0 หมายความว่าเราเปลี่ยนเดือนและมีวันสุดท้ายของเดือน
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash
อะไรประมาณนี้
แก้ไข.bashprofile
การเพิ่มของผู้ใช้:
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
จากนั้นเพิ่มรายการนี้ใน crontab:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
วันสุดท้ายของเดือนอาจเป็นวันที่ 28-31 ขึ้นอยู่กับเดือนนั้น (กุมภาพันธ์มีนาคมเป็นต้น) อย่างไรก็ตามในกรณีนี้วันถัดไปคือวันที่ 1 ของเดือนถัดไปเสมอ ดังนั้นเราสามารถใช้สิ่งนั้นเพื่อให้แน่ใจว่าเราทำงานบางอย่างเสมอในวันสุดท้ายของเดือนโดยใช้รหัสด้านล่าง:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh