1

We have a requirement where we have to run our job automatically on the last day of the month using the cron scheduler in Kubernetes. For example, for March, it should run on March 31st at 6pm. For April, it should run on April 30th at 6pm. Any help is appreciated. Thanks.

blacktide
  • 10,654
  • 8
  • 33
  • 53
Simmy
  • 11
  • 3
  • On the `schedule` spec, you can add something like `0 55 23 L * ?` (At 23:55:00pm, on the last day of the month, every month) – Hackerman Mar 28 '22 at 17:50
  • Thank you for replying.I have tried this syntax. But I am getting failed to parse int from L exception. I guess this is kubernetes specific – Simmy Mar 29 '22 at 01:19

2 Answers2

0

You can use the date command to control whether or not to execute another script or command:

# Tested using GNU coreutils date 8.30
/bin/sh -c "[ $(date -d +1day +%d) -eq 1 ] && echo 'It is the last day of the month!'"

# It is the last day of the month!

You can use this logic and your CronJob to run on the 28th-31st of each month, but only execute your script if tomorrow is the 1st of the month:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  # Run at 6pm on the 28th-31st of each month
  schedule: "0 18 28-31 * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cronjob
            image: busybox:1.35.0
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - "[ $(date -d +1day +%d) -eq 1 ] && job.sh"
          restartPolicy: OnFailure

Additionally, if there's a discrepancy on your version of date inside your base image and it doesn't support -d +1day, just offload the date check into your actual container job and have your job check to see if "tomorrow" is the 1st.

blacktide
  • 10,654
  • 8
  • 33
  • 53
  • I am getting below error Display time (using +FMT), or set time -u Work in UTC (don't convert to local time) [-s] TIME Set time to TIME -d TIME Display TIME, not 'now' -D FMT FMT (strptime format) for -s/-d TIME conversion -r FILE Display last modification time of FILE -R Output RFC-2822 date -I[SPEC] Output ISO-8601 date SPEC=date (default), hours, minutes, seconds or ns Recognized TIME formats: @seconds_since_1970 hh:mm[:ss] [YYYY.]MM.DD-hh:mm[:ss] YYYY-MM-DD hh:mm[:ss] [[[[[YY]YY]MM]DD]hh]mm[.ss] 'date TIME' form accepts MMDDhhmm[[YY]YY][.ss] instead – Simmy Mar 29 '22 at 10:59
  • That appears to be an issue with the version of `date` running in the image. I tested on Ubuntu 20.04 which is version 8.30 from GNU coreutils. You can still apply this logic elsewhere, like inside your "job" (the actual code doing the work) only run the job if "tomorrow" is the 1st. – blacktide Mar 29 '22 at 16:50
  • I tried with the modified cmd.still same error.I guess it is a date format mismatch issue.BusyBox v1.34.1 (2022-02-02 18:21:20 UTC) multi-call binary. Usage: date [OPTIONS] [+FMT] [[-s] TIME] Display time (using +FMT), or set time -u Work in UTC (don't convert to local time) [-s] TIME Set time to TIME -d TIME Display TIME, not 'now' -D FMT FMT (strptime format) for -s/-d TIME conversion -r FILE Display last modification time of FILE -R Output RFC-2822 date -I[SPEC] Output ISO-8601 date – Simmy Mar 29 '22 at 17:01
  • Does your cronjob call a REST service or something to perform the work? Perhaps you can just do the date check there instead? – blacktide Mar 29 '22 at 19:31
0

You can set the expression cron job "0 18 28-31 * *" It will run "At 18:00 on every day of the month from 28 through 31." In your source code, let's check time.Now + 1. If day of time.Now + 1 == 1, you call your function to process logic.

Example golang using github.com/robfig/cron/v3:

_, _ = c.AddFunc("0 18 28-31 * *", func() {
    tomorrow := time.Now().AddDate(0, 0, 1)
    if tomorrow.Day() == 1 {
        fmt.Println("This is the last day of the month")
    }
})