Saya perlu membuat pekerjaan CRON yang akan dijalankan pada hari terakhir setiap bulan. Saya akan membuatnya menggunakan cPanel.
Bantuan apa pun dihargai. Terima kasih
Saya perlu membuat pekerjaan CRON yang akan dijalankan pada hari terakhir setiap bulan. Saya akan membuatnya menggunakan cPanel.
Bantuan apa pun dihargai. Terima kasih
Jawaban:
Mungkin cara termudah adalah dengan melakukan tiga pekerjaan terpisah:
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
Itu akan berjalan pada 28 Februari meskipun, bahkan pada tahun kabisat jadi, jika itu masalah, Anda harus mencari cara lain.
Namun, biasanya jauh lebih mudah dan benar untuk menjalankan pekerjaan secepat mungkin pada hari pertama setiap bulan, dengan sesuatu seperti:
0 0 1 * * myjob.sh
dan memodifikasi skrip untuk memproses data bulan sebelumnya .
Ini menghilangkan semua kerepotan yang mungkin Anda hadapi dengan mencari tahu hari mana yang terakhir bulan itu, dan juga memastikan bahwa semua data untuk bulan itu tersedia, dengan asumsi Anda sedang memproses data. Berlari pada lima menit hingga tengah malam pada hari terakhir setiap bulan mungkin membuat Anda kehilangan apa pun yang terjadi antara saat itu dan tengah malam.
Ini adalah cara yang biasa untuk melakukannya, untuk sebagian besar pekerjaan akhir bulan.
Jika Anda masih benar - benar ingin menjalankannya pada hari terakhir setiap bulan, salah satu opsinya adalah dengan mendeteksi apakah besok adalah yang pertama (baik sebagai bagian dari skrip Anda, atau di crontab itu sendiri).
Jadi, sesuatu seperti:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
seharusnya menjadi awal yang baik, dengan asumsi Anda memiliki program yang relatif cerdas date
.
Jika date
program Anda tidak cukup maju untuk memberi Anda tanggal relatif, Anda dapat menyusun program yang sangat sederhana untuk memberi Anda hari esok bulan (Anda tidak memerlukan kekuatan penuhdate
), seperti:
#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;
}
lalu gunakan (anggap saja Anda menyebutnya tomdom
"hari esok bulan"):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
Meskipun Anda mungkin ingin mempertimbangkan untuk menambahkan pemeriksaan kesalahan karena keduanya time()
dan mktime()
dapat kembali -1
jika terjadi kesalahan. Kode di atas, karena alasan kesederhanaan, tidak memperhitungkannya.
Ada metode yang sedikit lebih pendek yang dapat digunakan mirip dengan salah satu metode di atas. Itu adalah:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
Juga, entri crontab dapat diperbarui untuk hanya memeriksa tanggal 28 hingga 31 karena tidak ada gunanya menjalankannya di hari-hari lain dalam sebulan. Yang akan memberi Anda:
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
dan tanggal POSIX tidak mendukung "-d +1day"
: - \ Solusi yang lebih rumit (dan jelek) adalah:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
Siapkan tugas cron untuk dijalankan pada hari pertama setiap bulan. Kemudian ubah jam sistem menjadi satu hari ke depan.
Bagaimana dengan yang ini, setelah Wikipedia?
55 23 L * * /full/path/to/command
Mengadaptasi solusi paxdiablo, saya menjalankannya pada 28 dan 29 Februari. Data dari tanggal 29 menimpa tanggal 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
?
Anda dapat menyiapkan tugas cron untuk dijalankan setiap hari dalam sebulan, dan menjalankannya skrip shell seperti berikut. Skrip ini menentukan apakah nomor hari esok kurang dari hari ini (yaitu jika besok adalah bulan baru), dan kemudian melakukan apapun yang Anda inginkan.
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
Beberapa implementasi cron mendukung tanda "L" untuk mewakili hari terakhir setiap bulan.
Jika Anda beruntung bisa menggunakan salah satu implementasi tersebut, semudah:
0 55 23 L * ?
Itu akan berjalan pada 11:55 pada hari terakhir setiap bulan.
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"
Untuk implementasi cron AWS Cloudwatch (Penjadwalan Lambdas, dll ..) ini berfungsi:
55 23 L * ? *
Tayang pukul 23:55 pada hari terakhir setiap bulan.
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
Lihat pertanyaan terkait di forum unix.com.
Anda bisa menghubungkan semua jawaban dalam satu baris cron dan hanya menggunakan date
perintah.
Periksa saja perbedaan antara hari dalam sebulan yaitu hari ini dan besok:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
Jika selisihnya di bawah 0 berarti kita mengganti bulan dan ada hari terakhir bulan tersebut.
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash
Bagaimana dengan ini?
edit .bashprofile
penambahan pengguna :
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
Kemudian tambahkan entri ini ke crontab:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
Hari terakhir setiap bulan bisa 28-31 tergantung pada bulan apa (Feb, Maret dll). Namun dalam salah satu kasus ini, hari berikutnya selalu tanggal 1 bulan depan. Jadi kita dapat menggunakannya untuk memastikan kita menjalankan beberapa pekerjaan selalu pada hari terakhir dalam sebulan menggunakan kode di bawah ini:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh