webdevops / go-crond

:alarm_clock: Cron daemon written in golang (for eg. usage in docker images)
GNU General Public License v2.0
124 stars 34 forks source link

[Support] Unable to run cron jobs on nth weekday of the month #42

Closed Draxter closed 1 year ago

Draxter commented 1 year ago

Hi, for some reason my cron job that is meant to run on every second Tuesday of the month, does not honour the day of month range that I give it in a 0 0 8-14 * 2 expression, which I double checked here

My setup: Docker image used: webdevops/go-crond:23.2.0-alpine CMD arguments: ["--auto", "--verbose"] My crontabs folder is copied like so: COPY --chmod=755 crontabs /etc/crontabs There I have a cron job /etc/crontabs/job_1 contains: 0 0 8-14 * 2 /files/job_1.sh

The Results docker logs go-crond 2>&1 | grep -i job_1

{"command":"/files/job_1.sh","crontab":"/etc/crontabs/job_1","level":"info","msg":"cronjob added","shell":"sh","spec":"0 0 8-14 * 2","time":"2023-06-21T09:04:22+12:00","user":"root"}
{"command":"/files/job_1.sh","crontab":"/etc/crontabs/job_1","level":"debug","msg":"executing","shell":"sh","spec":"0 0 8-14 * 2","time":"2023-06-27T00:00:00+12:00","user":"root"}
{"command":"/files/job_1.sh","crontab":"/etc/crontabs/job_1","elapsed_s":9306.533054711,"exitCode":0,"level":"info","msg":"finished","result":"success","shell":"sh","spec":"0 0 8-14 * 2","time":"2023-06-27T02:35:06+12:00","user":"root"}
{"command":"/files/job_1.sh","crontab":"/etc/crontabs/job_1","level":"debug","msg":"executing","shell":"sh","spec":"0 0 8-14 * 2","time":"2023-07-04T00:00:06+12:00","user":"root"}
{"command":"/files/job_1.sh","crontab":"/etc/crontabs/job_1","elapsed_s":9303.841112584,"exitCode":0,"level":"info","msg":"finished","result":"success","shell":"sh","spec":"0 0 8-14 * 2","time":"2023-07-04T02:35:10+12:00","user":"root"}

Looks like the 8-14 day of month range is ignored, and the job runs every Tuesday. I also double chcked the date and time on the container, and it's correct. Any ideas?

Draxter commented 1 year ago

I have also tried an alternative cron expression 0 0 ? * TUE#2

However gocrond returns a syntax error:

{"command":"/files/job_1.sh","crontab":"/etc/crontabs/job_1","level":"error","msg":"cronjob failed adding: failed to parse int from TUE#2: strconv.Atoi: parsing \"TUE#2\": invalid syntax","shell":"sh","spec":"0 0 ? * TUE#2","time":"2023-07-05T09:02:04+12:00","user":"root"}
smlx commented 1 year ago

Looks like the 8-14 day of month range is ignored, and the job runs every Tuesday. I also double chcked the date and time on the container, and it's correct. Any ideas?

From crontab(5):

Commands are executed by cron(8) when the minute, hour, and month of year fields match the current time, and when at least one of the two day fields (day of month, or day of week) match the current time.

So that means commands are executed if either of the third (day of month) or fifth (day of week) fields match.

In your case, the command will run at midnight every day between the 8th and 14th (inclusive) of every month, and on every Tuesday.

Edit: Sorry, forgot to mention you can achieve "the second Tuesday of every month" like this:

0 0 8-14 * * [ $(date +\%u) = 2 ] && /files/job_1.sh
Draxter commented 1 year ago

@smlx Sounds like you are right, and that first cron expression is incorrect.

For now I worked around it by using a ‘test’ command before running job_1. It checks whether its Tuesday and cron expression runs the job between 8th and 14th.

Expressions like ‘TUE#2’ still aren’t supported though, which are a part of a cron spec. Might be a useful feature to add.

smlx commented 1 year ago

Expressions like ‘TUE#2’ still aren’t supported though, which are a part of a cron spec. Might be a useful feature to add.

That's Java's crontab-like syntax, and I've never seen it implemented elsewhere. It is not part of any specification I'm aware of - certainly not POSIX crontab.

Draxter commented 1 year ago

Fair enough, I stand corrected. I guess I will need to stick with the test workaround for unusual time intervals like “every second Tuesday”.

Edit: Thanks @smlx, I came up with something similar: test $(date +\%u) -eq 2 && /files/job_1.sh

Though even that is not ideal, as it counts as a failure on days other than Tuesday as far as gocrond is concerned, which triggers my alerting :(

smlx commented 1 year ago

Though even that is not ideal, as it counts as a failure on days other than Tuesday as far as gocrond is concerned, which triggers my alerting :(

You can fix this using an if statement:

if [ $(date +\%u) = 2 ]; then /files/job_1.sh; fi