troglobit / finit

Fast init for Linux. Cookies included
https://troglobit.com/projects/finit/
MIT License
632 stars 63 forks source link

Expand manual:yes to work for run/task and sysv as well as service #274

Closed hongkongkiwi closed 2 years ago

hongkongkiwi commented 2 years ago

manual:yes seems to be not supported for task definitions (?)

task [S123456789] manual:yes name:test /tmp/test > /tmp/test2 -- test

This appears to execute immediately even though I'm asking it to be manual.

troglobit commented 2 years ago

Hmm, yeah that doesn't sound right. I'll look into it!

troglobit commented 2 years ago

Turns out manual:yes was limited to type service when it was introduced in 2018, 6a7f1157. I should have been more careful when documenting it.

I'm adding this to the v4.4 release cycle, opening it up for run/task and sysv types as well.

hongkongkiwi commented 2 years ago

Very helpful, how does manual:yes work when used together with conditions?

troglobit commented 2 years ago

A service with manual:yes will remain in halted state until it's "unblocked" by the user calling initctl start foo. This allows the service to transition to ready, optionally going to setup first if pre: is defined. When in ready the aggregation of all conditions are evaluated, if a condition is not asserted the service remains in ready, otherwise it will be allowed to be started.

One possibility I see here is to discuss the semantics for manual:yes on both run and task, which by definition only run once per runlevel (or as we found out, after an initctl reload foo :)

Alternatives I see:

  1. Behave as before, manual only means it's up to the user to start them
  2. A manual run/task is allowed to run more than once per runlevel, at the discretion of the user

I think alternative 2 is very appealing.

hongkongkiwi commented 2 years ago

I like (2) as it fits my use case. But could I suggest a slight modification because I think having behaviour only for manual:yes could be confusing.

What about this....

This way the behaviour is very clear and it doesn't break any backwards compatibility. The user can repeatedly run initctl start <task> as they see fit and they will only ever get a single run (in the runlevel) as they might expect.

HOWEVER if the user knows that they absolutely want to run the task again (which is my use case) then they can use initctl start -f <task> and know that the task will be immediately run (if it's not already running and conditions are matched).

In future, it might be nice to have another flag to ignore conditions as well, say -ff but that might get complicated now I guess.

troglobit commented 2 years ago

I dunno, since manual:yes has been reserved only for service stanzas before, I'd say we can set the scene as we like. Also, we don't support option flags on sub-commands to initctl, much like ip/bridge commands in iproute2, and that would be quite a bit of work to implement for this single feature. That's not the argument though ...

... I argue that since run/task are by their very nature different from service, we can define what manual:yes means for them. I posit that manual:yes means "leave behavior up to user". We should of course also allow manual status to be shown by initctl, e.g.: "manual: managed by user" vs "manual: managed by finit", or similar.

hongkongkiwi commented 2 years ago

Just realised -f is used for something, perhaps we could use something else even a whole new command.

initctl force-start <name>

hongkongkiwi commented 2 years ago

I see, so if you want a task to be able to be run multiple times AND automatically you would have two task definitions, one manual and one automatic. The automatic one will only ever run once (or with a specific service reload) and the manual task will always run when requested?

troglobit commented 2 years ago

I see, so if you want a task to be able to be run multiple times AND automatically you would have two task definitions, one manual and one automatic. The automatic one will only ever run once (or with a specific service reload) and the manual task will always run when requested?

Yes, that's the way I see it.

hongkongkiwi commented 2 years ago

Thank you for completing this, very useful for me.

Wanted to ask your thoughts on the status, so at the moment the script shows as "stopped". I found this a bit confusing when using the manual:yes.

Could I suggest a new status called "manual" or perhaps setting "ready" like it's waiting for the condition of manually running to be fufilled?

This way I can look at the list and instantly know the status.

hongkongkiwi commented 2 years ago

I also found that if a task that's set with manual:yes task exits with non zero exit code, then will show as "stopped". So there's no way to know if it was run and succeeded, waiting to be run or ran and failed.

I was hoping to get a clear overview of the system by looking at the initctl status command .

troglobit commented 2 years ago

OK, hope this helps:

Status : stopped (code=exited, status=0/SUCCESS, manual=yes)

A manual:yes task that exits with a non-zero exit code looks like this:

Status : stopped (code=exited, status=1/FAILURE, manual=yes)

To make this easier to script we have #273 which I hope to get back to soon as well.

troglobit commented 2 years ago

This one kept bugging me. So I decided to change the implementation for manaul:yes run/tasks slightly in 96257cc. With this last change all run/tasks end up in state done instead of manual:yes tasks going to stopped.

Calling initctl start foo still restarts them, only change is the end state. Hope this helps.

hongkongkiwi commented 2 years ago

Great!! I like it :) I will test it after a code merge this week