Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support @reboot command #30

Open
hongkongkiwi opened this issue Apr 10, 2018 · 22 comments
Open

Support @reboot command #30

hongkongkiwi opened this issue Apr 10, 2018 · 22 comments
Labels

Comments

@hongkongkiwi
Copy link

hongkongkiwi commented Apr 10, 2018

Hi there,

I'm currently running supercronic in a docker and it's working great.

I would like to run my script on "boot" e.g. when supercronic is started, as well as at a set interval. Normally in many cron versions we can use the standard @reboot to run a script on reboot, but in my testing it looks like supercronic doesn't currently support this.

Would it be possible to add this functionality? I notice that other shortcuts such as @hourly are supported.

I do have a work-around which is to run a shell script /start-container which simply runs my script and then runs supercronic, but it seems a bit awkward!

@krallin
Copy link
Collaborator

krallin commented Apr 18, 2018

What's your expectation for what @reboot would do? Run the job upon Supercronic starting up?

(I'm a little concerned about this being potentially confusing, since that's not what you'd normally expect from a @reboot in regular cron)

@hongkongkiwi
Copy link
Author

hongkongkiwi commented May 11, 2018

Yes that is right, I would expect supercronic to run the script when it first starts up.

That means I can have both an hourly and a startup command all in the same cron file (which makes it pretty clear).

Here is my use case.

  1. When the Docker starts up it runs a run system called runit.
  2. Runit must start as PID 1, so therefore entrypoint looks like this ENTRYPOINT ["/sbin/runit-init"]
  3. Supercronic is a runit service so it will get started immediately, my script runs every 30 minutes
  4. My script that is running is a bash script (and not a service) so it cannot be started using runit

So you can see my problem, there's no way in this configuration to run some arbitrary script after runit. How I would handle this on other systems might be to do something like @reboot in the crontab so that after the cron daemon starts up it will run this script once.

The only other workaround for now is to have a service that runs once off scripts, but that's quite awkward.

@cgons
Copy link

cgons commented May 27, 2018

I'm looking for this feature as well.

Maybe rather than @reboot, we call it @cronstart so as not to confuse with the act of a system reboot.

With @reboot, I fear one might infer the prefixed cron job will only run on system reboots.

@krallin - Would you be open to a PR adding this feature?

@krallin
Copy link
Collaborator

krallin commented May 28, 2018

@cgons yes, with the minor caveat that I think @start would be a simpler / appropriate name for the event. We'll want to make sure to document that this is non-standard though.

@hongkongkiwi
Copy link
Author

Sounds like a great solution! Looking forward to the PR.

@cgons
Copy link

cgons commented May 29, 2018

Awesome, @start it is! I'll try and get started ASAP.

BTW, is this the correct place to talk about implementation details (ie what I plan to change/add etc...)?

@krallin
Copy link
Collaborator

krallin commented May 30, 2018

@cgons sure, that's fine 👍

@hongkongkiwi
Copy link
Author

Any progress on this @cgons ? I work around this by adding a docker-entrypoint.sh file, but I would love to get rid of this extra process handling and have everything done within supercronic.

@cgons
Copy link

cgons commented Dec 13, 2018

Sorry, I had to go an pat. leave for a few months and ended up having negative free time to work on this. I'm back now and I want to try and get this working over the next few days/weeks.

I'll post here with an update. Be on my case though as that's a motivator to get this implemented! :)

@cgons
Copy link

cgons commented Dec 15, 2018

@krallin - I was thinking of creating a PredefinedExpression class that implements the Expression interface and returns zero value time after it has been run once (via the implemented Next() method).

Inside parseJobLine() I would check if the line starts with @ and if so, attempt to parse it as a PredefinedExpression. If the @ does not match the list of predefined expressions (which for now would be just @start), then it would return a error and we can then attempt to parse it using cronexpr.

I have to think a little more about how to keep track of when the job was run and where to store that state. I should probably take advantage of the cronIteration counter...

Let me know what you think.

@krallin
Copy link
Collaborator

krallin commented Dec 17, 2018

I think you should instead create a separate interface that wraps the existing cron expression interface, because you're also going to need a IsDone method or some such to represent that the StartJob goroutine should exit after running this job once.

I'm not clear on why you suggest Next() should return 0. I'm not certain I understand what this achieves here?

@cgons
Copy link

cgons commented Dec 19, 2018

Yep, that's what I'll have to do. I was trying to get away with making a minimal amount of changes but, as you pointed out, that won't really work.

I'll get this working in a branch on my fork and then ping you. I can then make any changes you'd like to see.

@romain-dartigues
Copy link

yes, with the minor caveat that I think @start would be a simpler / appropriate name for the event. We'll want to make sure to document that this is non-standard though.

I'm not really fan of having a new (non-standard, supercronic-specific) directive, like @start.
@reboot is already documented as "schedule this job only once, when crond starts up" in dcron.

The Vixie cron manual (which, AFAIK introduced this directive) just says "run once after reboot"; but the debian version of the manual page states: "Please note that startup, as far as @reboot is concerned, is the time when the cron(8) daemon startup. In particular, it may be before some system daemons, or other facilities, were startup. This is due to the boot order sequence of the machine.".

@dmaj
Copy link

dmaj commented Jun 16, 2019

Sorry, couldn't wait until someone started the implementation. I implemented the issue. Unfortunately this was my first contact with Golang. So please don't expect too much :-). Besides, it is somehow a hack ... But for my purposes it works.

I have extended the translation table in Cronexpr: "@start", "*/1 * * * * * * *".
So this job starts every second.
In the supercronic I check if the job was generated from an @start and terminate it after a single run.
To leave some time for @start processing, I introduced a parameter "-delay".
The line with @start must be at the first position.
And @start may occur only once.

https://github.com/dmaj/supercronic
https://github.com/dmaj/cronexpr

Sample:
@start touch /home/golang/etc/test.txt
*/1 * * * * * * echo "hello"

@fbartels
Copy link

Maybe this is interesting for others as well. I solved the @reboot topic for me by simply doing a one off execution of my cron tasks before actually starting supercronic. This is easily doable since I am not mounting my crontab file into the container, but actually generate it at container startup. This has for me the added benefit that I am making sure that the cron jobs work at all (else the container would fail to start).

Code is at https://github.com/zokradonh/kopano-docker/blob/e0792a39a5d5ea83203647f303350101df97e590/scheduler/start.sh#L35

@phin1x
Copy link

phin1x commented Jun 19, 2019

i created a pull request to implement this issue. in the first run of the main loop i execute all jobs with the expression @start. after then the other periodic jobs will be scheduled.
the pr is reload safe.

@hongkongkiwi
Copy link
Author

Awesome! Can we get this merged?

@MikeC-BC
Copy link

would love to see this merged

@dex4er
Copy link

dex4er commented Jul 3, 2020

Actually I would prefer @reboot instead of @start as it is supported by all cron replacements. You can just make it clear in documentation that @reboot means "run once after cron is started".

I would avoid using nonstandard name as @start because probably it would break some existing parsers.

krallin pushed a commit to krallin/supercronic that referenced this issue Nov 14, 2020
Allow library to be used in parallel
@dmitrypol
Copy link

was this ever implemented? Would be a really nice feature

@divStar
Copy link

divStar commented May 17, 2023

I would also like to know if there is a way to run a script only once. I do not exactly need a @reboot command or anything. The reason is: I use a container I created based on alpine and supercronic and on most occasions I use it to comfortably run scripts in a loop, but I've had occasions I only wanted to run the script once.

Currently I need to override the initial command in my deployment.yaml, but it'd be much nicer if I just could specify an environment variable or anything really to only execute a script once (a CLI command, that I could insert into my query.sh script would also be fine). I do not feel like using pkill or something like that.

@mmguero
Copy link

mmguero commented Aug 13, 2024

I'm still crossing my fingers on this. It's been a year since the last update, any movement on this (whether it's @start or @reboot or @cronstart I don't really care :D)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests