Tôi cần tạo một công việc CRON sẽ chạy vào ngày cuối cùng của mỗi tháng. Tôi sẽ tạo nó bằng cPanel.
Bất kỳ trợ giúp được đánh giá cao. Cảm ơn
Tôi cần tạo một công việc CRON sẽ chạy vào ngày cuối cùng của mỗi tháng. Tôi sẽ tạo nó bằng cPanel.
Bất kỳ trợ giúp được đánh giá cao. Cảm ơn
Câu trả lời:
Có thể cách dễ nhất là làm ba công việc riêng biệt:
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
Tuy nhiên, điều đó sẽ diễn ra vào ngày 28 tháng 2, ngay cả vào những năm nhuận, vì vậy, nếu đó là một vấn đề, bạn sẽ cần phải tìm một cách khác.
Tuy nhiên, việc thực hiện công việc càng sớm càng tốt vào ngày đầu tiên của mỗi tháng thường dễ dàng và chính xác hơn rất nhiều , với những điều như:
0 0 1 * * myjob.sh
và sửa đổi kịch bản để xử lý trước dữ liệu tháng.
Điều này loại bỏ mọi phức tạp mà bạn có thể gặp phải khi tìm ra ngày nào là ngày cuối cùng của tháng và cũng đảm bảo rằng tất cả dữ liệu cho tháng đó đều có sẵn, giả sử bạn đang xử lý dữ liệu. Chạy vào lúc năm phút đến nửa đêm vào ngày cuối cùng của tháng có thể thấy bạn bỏ lỡ bất kỳ điều gì xảy ra từ sau đó đến nửa đêm.
Đây là cách thông thường để làm, đối với hầu hết các công việc cuối tháng.
Nếu bạn vẫn thực sự muốn chạy nó vào ngày cuối cùng của tháng, một tùy chọn là chỉ cần phát hiện xem ngày mai có phải là ngày đầu tiên hay không (như một phần của tập lệnh của bạn hoặc trong chính crontab).
Vì vậy, một cái gì đó như:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
nên là một khởi đầu tốt, giả sử bạn có một date
chương trình tương đối thông minh .
Nếu date
chương trình của bạn không đủ nâng cao để cung cấp cho bạn những ngày tương đối, bạn có thể chỉ cần tổng hợp một chương trình rất đơn giản để cung cấp cho bạn ngày mai trong tháng (bạn không cần toàn bộ sức mạnh của date
), chẳng hạn như:
#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;
}
và sau đó sử dụng (giả sử bạn đã gọi nó tomdom
cho "ngày mai trong tháng"):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
Mặc dù bạn có thể muốn xem xét thêm tính năng kiểm tra lỗi vì cả hai time()
và mktime()
có thể trả lại -1
nếu có sự cố. Đoạn mã trên, vì lý do đơn giản, không tính đến điều đó.
Có một phương pháp ngắn hơn một chút có thể được sử dụng tương tự như một trong những phương pháp ở trên. Đó là:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
Ngoài ra, mục crontab có thể được cập nhật để chỉ kiểm tra vào ngày 28 đến ngày 31 vì việc chạy nó vào những ngày khác trong tháng là vô nghĩa. Cái nào sẽ cung cấp cho bạn:
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
và ngày POSIX không hỗ trợ "-d +1day"
: - \ Một giải pháp phức tạp hơn (và xấu xí hơn) sẽ là:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
Thiết lập một công việc cron để chạy vào ngày đầu tiên của tháng. Sau đó, thay đổi đồng hồ của hệ thống để đi trước một ngày.
Điều chỉnh giải pháp của paxdiablo, tôi chạy vào ngày 28 và 29 tháng Hai. Dữ liệu từ ngày 29 ghi đè lên ngày 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
?
Bạn có thể thiết lập một công việc cron để chạy vào mỗi ngày trong tháng và để nó chạy một tập lệnh shell như sau. Tập lệnh này tính xem số ngày của ngày mai có ít hơn ngày hôm nay hay không (tức là nếu ngày mai là một tháng mới) và sau đó làm bất cứ điều gì bạn muốn.
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
Một số triển khai cron hỗ trợ cờ "L" để đại diện cho ngày cuối cùng của tháng.
Nếu bạn may mắn được sử dụng một trong những cách triển khai đó, nó đơn giản như sau:
0 55 23 L * ?
Điều đó sẽ chạy lúc 11:55 tối vào ngày cuối cùng của mỗi tháng.
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"
Để triển khai AWS Cloudwatch cron (Lên lịch Lambdas, v.v.), điều này hoạt động:
55 23 L * ? *
Chạy lúc 11:55 tối vào ngày cuối cùng của mỗi tháng.
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
Kiểm tra một câu hỏi liên quan trên diễn đàn unix.com.
Bạn chỉ có thể kết nối tất cả các câu trả lời trong một dòng cron và chỉ sử dụng date
lệnh.
Chỉ cần kiểm tra sự khác biệt giữa ngày trong tháng là hôm nay và ngày mai:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
Nếu sự khác biệt này dưới 0 có nghĩa là chúng tôi thay đổi tháng và có ngày cuối cùng của tháng.
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash
Cái này thì sao?
chỉnh sửa .bashprofile
cách thêm của người dùng :
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
Sau đó, thêm mục nhập này vào crontab:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
Ngày cuối cùng của tháng có thể là 28-31 tùy thuộc vào tháng đó là gì (tháng 2, tháng 3, v.v.). Tuy nhiên, trong một trong hai trường hợp này, ngày hôm sau luôn là ngày đầu tiên của tháng sau. Vì vậy, chúng tôi có thể sử dụng điều đó để đảm bảo chúng tôi luôn chạy một số công việc vào ngày cuối cùng của tháng bằng cách sử dụng mã bên dưới:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh