bnosac / cronR

A simple R package for managing your cron jobs.
Other
288 stars 38 forks source link

cronR replaces days_of_week="*" with "0,1,2,3,4,5,6" causes monthly cron to run daily on linux #38

Open asmwbrown opened 3 years ago

asmwbrown commented 3 years ago

Thank you for this package, I am finding it very useful and am trying to use cronR more generally rather than linux-level cron commands.

I have hit a behaviour where cronR replaces days_of_week="*" with "0,1,2,3,4,5,6" causes monthly cron to run daily on linux. This possible value for days_of_week is mentioned in the cronR vignette so I hope it is valid but the output is not given so I am not totally sure if this is an issue or expected (undocumented?) behaviour.

I have checked and I think the 2 values (resulting vs expected) have different behaviours at least for Linux and maybe generally on Unix-like systems.

Resulting: 
0 5 15 * 0,1,2,3,4,5,6 <cmd>
Expected: 
0 5 15 * * <cmd>

As a workaround I am using frequency = '0 5 15 * *' without days_of_week or days_of_month options set.

Thanks in advance! Arlene

Supporting info:

--- Code ---- 

library("cronR")

cmd <- cronR::cron_rscript("./scripts/r/EHC001_run_report.R") 
cmd <- paste(paste("cd '", getwd(), "' && ", cmd, sep="")) 

# Add cron to crontab 
cronR::cron_add(command=cmd, frequency = "monthly", at="05:00", days_of_month = "15", 
                days_of_week = "*", id="EHC001", 
                        tags = c("monthly", "EHC001 - Communicating Devices"), 
                        description = "Communication status from estate health check data: Execute at 0500 UTC on the 15th of the month") 

--- Resulting output 

> cronR::cron_add(command=cmd, frequency = "monthly", at="05:00", days_of_month = "15", 
+                 days_of_week = "*", id="EHC001", 
+                 tags = c("monthly", "EHC001 - Communicating Devices"), 
+                 description = "Communication status from estate health check data: Execute at 0500 UTC on the 15th of the month") 
Adding cronjob:
---------------

## cronR job
## id:   EHC001
## tags: monthly, EHC001 - Communicating Devices
## desc: Communication status from estate health check data: Execute at 0500 UTC on
##   the 15th of the month
0 5 15 * 0,1,2,3,4,5,6 cd '/home/arlene.brown/projects/EHC001 - Communicating Devices' && /opt/R/4.0.2/lib/R/bin/Rscript './scripts/r/EHC001_run_report.R'  >> './scripts/r/EHC001_run_report.log' 2>&1

--- Linux-level console output for information
rlene.brown@aw17laldvrss001:~/projects/EHC001 - Communicating Devices$ uname -a 
Linux aw17laldvrss001 5.4.0-1037-aws #39~18.04.1-Ubuntu SMP Fri Jan 15 02:48:42 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
arlene.brown@aw17laldvrss001:~/projects/EHC001 - Communicating Devices$ crontab -l 

## cronR job
## id:   EHC001
## tags: monthly, EHC001 - Communicating Devices
## desc: Communication status from estate health check data: Execute at 0500 UTC on
##   the 15th of the month
0 5 15 * 0,1,2,3,4,5,6 cd '/home/arlene.brown/projects/EHC001 - Communicating Devices' && /opt/R/4.0.2/lib/R/bin/Rscript './scripts/r/EHC001_run_report.R'  >> './scripts/r/EHC001_run_report.log' 2>&1

--- Similar example from cronR vignette: 
cron_add(cmd, frequency = 'monthly', id = 'job8', at = '10:30', 
  days_of_month = 'first', days_of_week = '*')

--- I have referred to this web page as part of troubleshooting to confirm my understanding of Linux cron behaviour for the resulting / expected strings: https://crontab.guru/#0_5_15_*_0,1,2,3,4,5,6 https://crontab.guru/#0_5_15_*_*

asmwbrown commented 3 years ago

The substitution happens in cron_add.R line 155 where parse_day_of_week is called

days_of_week [1] "*" day_of_week <- paste( unique( sort(sapply(days_of_week, parse_day_of_week))), collapse=",") day_of_week [1] "0,1,2,3,4,5,6"

In parse_time_slots.R function parse_day_of_week there is no check specifically for "*" string that will fix the problem

I think the same issue exists for parse_day_of_month when days_of_month = "*" but I haven't tested that scenario explicitly

jwijffels commented 3 years ago

Yeah, you are right. This results in an OR in cron (see as well https://stackoverflow.com/questions/34357126/why-crontab-uses-or-when-both-day-of-month-and-day-of-week-specified) Workaround is indeed to pass frequency = '0 5 15 * *' as you indicate