Menjalankan pekerjaan cron pada hari Senin pertama setiap bulan?

31

Saya ingin menjalankan pekerjaan dari cron pukul 8.30 pada hari Senin pertama setiap bulan. Halaman Wikipedia cron mengatakan

Sementara biasanya pekerjaan dijalankan ketika waktu / tanggal bidang spesifikasi semua sesuai dengan waktu dan tanggal saat, ada satu pengecualian: jika kedua "hari bulan" dan "hari minggu" dibatasi (tidak "*"), maka baik bidang "hari bulan" (3) atau bidang "hari dalam seminggu" (5) harus cocok dengan hari ini.

(penekanan saya)

Apakah itu berarti saya tidak dapat melakukan hari Senin pertama di bulan itu, saya hanya dapat melakukan hari pertama (atau apa pun) dalam sebulan? Saya tidak bisa memikirkan cara untuk memutarnya.

Max Williams
sumber
slhck - yang terdengar seperti solusi yang baik - maukah Anda memperluasnya menjadi jawaban dengan kode lengkap? maka saya akan menandainya sebagai benar :)
Max Williams

Jawaban:

38

Anda dapat memasukkan kondisinya ke perintah crontab aktual:

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

Sekarang, jika kondisi ini benar pada salah satu dari tujuh hari pertama dalam sebulan, Anda memiliki hari Senin pertamanya. Perhatikan bahwa dalam crontab, sintaks persen perlu diloloskan:

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

Ganti echoperintah dengan perintah aktual yang ingin Anda jalankan. Saya menemukan pendekatan yang sama juga.

slhck
sumber
sebenarnya, slhck, saya berbicara terlalu cepat - ini tidak berfungsi di crontab saya: sepertinya ada masalah dengan tes tanggal karena beberapa alasan. Ini bekerja di baris perintah [ "$(date '+%a')" = "Mon" ] && echo "It's Monday"seperti halnya [ $(date '+%a') = "Mon" ] && echo "It's Monday" Tapi, di crontab tampaknya gagal pada tes ini. Saya tidak bisa mendapatkan umpan balik yang berguna dari cron baik: saya mencoba ini [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1untuk menangkap output kesalahan ke dalam log tetapi itu tidak berfungsi baik: /
Max Williams
Hm Bisakah Anda memeriksa apakah dateoutput sudah benar? Misalnya, biarkan cronperintah dijalankan yang menampilkan ini ke file: date '+%a' > ~/datetest 2>&1- lalu periksa apakah itu menghasilkan string yang tepat untuk dibandingkan.
slhck
1
Saya menemukan masalah - persen +%adibutuhkan melarikan diri ketika berada di crontab, yaitu garis yang dibutuhkan untuk menjadi ini: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". Jika Anda dapat memperbarui jawaban Anda dengan itu akan sangat membantu pembaca di masa depan :) Terima kasih lagi - maks
Max Williams
Oh, sekarang saya mengerti mengapa. Senang itu bekerja sekarang, terima kasih telah mencobanya!
slhck
12

Saya memiliki komputer dengan lokal pada bahasa Spanyol, jadi, pendekatan ini tidak berfungsi untuk saya karena mon berubah menjadi lun

Bahasa lain juga akan gagal, jadi, saya melakukan sedikit variasi pada jawaban yang diterima yang menghilangkan kendala bahasa:

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"
cumanacr
sumber
+1 ¡Muy bien, señor!
JakeGould
1
Gracias ¡Pura vida! ; D
cumanacr
Ini harus menjadi jawaban yang diterima. Saya memiliki lokal Belanda yang juga menggunakan nama yang berbeda untuk hari kerja. Dan menggunakan angka juga terasa lebih bersih daripada membandingkan string untuk menentukan hari dalam seminggu.
0ne_Up
7

Saya merasa lebih mudah ketika tidak perlu menangani angka hari.

Jalankan Senin Pertama bulan:

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

yaitu jika bulan 1 minggu yang lalu tidak sama dengan bulan saat ini maka kita berada di hari 1 1 (= Senin) bulan itu.

Begitu pula untuk Jumat Ketiga

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

yaitu jika bulan 3 minggu yang lalu berbeda dengan bulan saat ini maka kita berada di hari ke-6 (= Jumat) bulan itu

joel
sumber
Hari 6 minggu adalah hari Sabtu bukan hari Jumat.
Robert
4

Saya telah menjadwalkan pekerjaan untuk dijalankan pada Senin ke-4 setiap bulan pada pukul 16:00 sebagai berikut:

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

Sejauh yang saya tahu TIDAK mungkin hanya menggunakan crontab, namun seseorang dapat menggunakan fungsi wrapper untuk memilih hari yang benar dari entri contab "tujuh hari pertama bulan"; lihat ini dari entri.

Script wrapper akan menjadi

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

dan Anda perlu menjalankannya (dengan asumsi itu disebut wrapper.sh dan tersedia secara global) menggunakan entri crontab

0 0 * * 1 wrapper.sh
elemakil
sumber
terimakasih elemaki. Saya memikirkan solusi serupa menggunakan beberapa kode tambahan di dalam tugas yang dijalankan, membuatnya untuk menguji apakah ini hari Senin pertama bulan di dalam skrip, dan kemudian memanggilnya setiap hari Senin di crontab. Script ruby ​​jadi mudah untuk menguji hari minggu ke-5. Tapi saya berharap hanya ada satu cara crontab.
Max Williams
1

Anda dapat mencoba menjalankan cronjob selama tujuh hari pertama bulan ini dan menjalankannya hanya pada hari Senin.

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

Di atas harus bekerja untuk Anda.

simer
sumber
+1 lebih sukses tekan ransum kemudian berjalan untuk minggu pertama dan periksa untuk Senin. :-)
xmedeko
1

Saya sarankan untuk digunakan

"$(/bin/date '+%\w')" = "1"

dari pada

"$(date '+\%a')" = "Mon"

untuk menghindari masalah lokal.

Manus Freedom
sumber
0

Saya membuat solusi umum untuk masalah seperti ini, ini berfungsi untuk pertama, kedua, ketiga ..... hari kerja terakhir di bulan itu.

Anda bisa menggunakannya seperti ini:

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"

Script run-if-today memeriksa rentang hari kerja dan tanggal minggu yang diinginkan, jika keduanya cocok maka menghasilkan 0, jika tidak 1.

Periksa kodenya di sini. https://github.com/xr09/cron-last-sunday

MGP
sumber
0

Saya percaya ini memecahkan masalah dengan lebih elegan:

30 8 1-7 * 1 /run/your/job.sh
symcbean
sumber
Doh! : "Jika kedua bidang dibatasi (yaitu, bukan *), perintah akan dijalankan ketika salah satu bidang cocok dengan waktu saat ini."
symcbean
Juga pada bulan Februari (yang berakhir 28) tidak akan berjalan setiap 4 tahun.
igraczech
"salah" berarti salah satu dari mereka, bukan "keduanya". ini akan berjalan setiap hari selama 7 hari pertama dalam sebulan.
minusf
Baris ini akan menjalankan perintah pada hari pertama hingga ketujuh setiap bulan, dan juga pada setiap hari Senin
Tomasz Jakub Rup
0

Pada Solaris 10 saya harus memformat kondisi sebagai berikut:

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

Karena saya menafsirkan pernyataan cron saya menggunakan php dan js, saya tidak bisa menggunakan bash. Akhirnya saya menemukan bahwa itu adalah sebenarnya mungkin hanya dengan cron:

0 30 8 * 1/1 MON#1

Semoga ini bisa membantu orang lain. Apapun, saya berharap Anda semua hari yang indah. :-)

kramer65
sumber
-1
0 9 1-7 * 1 * 

Ini akan bekerja untuk setiap Senin setiap bulan.

SIBHI S
sumber
Sebuah jawaban telah diterima, apakah jawaban Anda lebih baik, berbeda atau bermanfaat untuk versi yang lebih baru, dll.
mic84