Closed hongkongkiwi closed 1 year ago
A generic file/foo/exists was tried a while ago, but scrapped due to the added complexity in Finit. There are usr conditions you can use instead, and possibly an mdev script to enable the service when ttyUSB1 is plugged in. That's what I'd recommend to use instead.
I think a file/dir exists or file/dir modified would be really handy, but I totally understand why it would be scrapped. The same could be achieved in multiple ways.
I guess your talking about issue #135 for this.
When you clear an a
Loss of conditions stops services, yes.
I am able to handle this with custom conditions and mdev, although I would love to have a <dev/something> in future.
What we have, which I forgot to mention, is a tty.so plugin, which can start a getty on demand, e.g. when someone plugs in a usb-to-serial adapter. However, now (years ago but ok) that we've refactored tty's into a service variant, maybe your idea isn't so far-fetched after all ... reopening.
I was thinking about this and maybe it could be turned into a more generic thing. I think this would be helpful.
For example, say you wanted dropbear to be started when a file is created, e.g. /run/dropbear so you could specify a condition: <file/run/dropbear/exist> and finit would hold the inotify for that path. This would extend into <dir/dev/ttyUSB2/exist> naturally.
As an extension to this, you could have this: <file/etc/mosquitto.conf/update> which would reload the service when that file is updated.
This would turn it into a very flexible wrapper of inotify.
I re-read above and realised that this used to be here but was scrapped, just musing again about the device functionality. I'm also using files in /run for some basic info (a sort of text db) so was thinking that would also be helpful.
This would indeed be very powerful.
Problem is inotify in the kernel listens to directories, so there could potentially be lots of activity to discard for each such file monitor ... however, this could be handled by a helper daemon, which in turn could generate the conditions Finit reacts to. Finit could "simply" instruct it's helper daemon listen to a certain set of paths after it has read its .conf files and figured out all the current <file/foo/state>
conditions.
Did you misspell above <dir/dev/ttyUSB2/exist>
or am I missing a point here? Otherwise I'll guess /dev/ttyUSB2 is a file, and you meant <file/...>
.
This is quite a lot of work though, and I have clients eagerly awaiting v4.3 right now, so even though it's intriguing it'll have to wait for the next release cycle.
How do you think if we narrowed down this feature request to being able to set custom watches on paths in the config? For example in the config we could have:
watch_path=/dev/ttyUSB2
watch_path=/my/custom/filepath
We could even have this as a compile time option if it's easier? (although more flexible if it can be in the config).
This could be limited to specific paths and then we are only adding a few extra watches for finit to monitor.
Then the condition could be <notify/path/exist>
.
This makes it super flexible and you could even monitor something like /proc/device-tree/.... and have it set a condition based on whats in the dtb file.
There are lots of possibilities and I've spent a great deal of time contemplating all this. I created Finit's keventd
for handling <sys/...>
conditions, primarily for tracking ACPI power state changes. I'm thinking it could be extended to handle other types of kernel NETLINK_KOBJECT_UEVENT
s as well, e.g. devices being added/removed.
For generic files another helper daemon could be added, perhaps an inotifyd
. Maybe inotifywatch
can be used for this, which would make this part an integration/distributor thing rather than having to be supported natively by Finit. Documenting the API (/run/finit/cond/*
) for the condition subsystem is something I've been considering for a while, and since my former employer use that heavily for their own conditions, it's effectively frozen.
That’s a good idea, can I add my own conditions as files in /run/finit/cond ? Right now I’m setting conditions during startup using initctl (such as in mdev scripts), and it may be what’s causing timeouts for me with finit sometimes.
Could I directly add files into the conditions path and finit will pick it up without a reload?
Yes, but hang on. In https://github.com/troglobit/finit/issues/254#issuecomment-1113945861 I detailed which initctl
commands are supported in runlevel S, that don't block or communicate with Finit. User conditions with initctl cond [set | clear]
are among those supported, so if you're setting/clearing/getting conditions, that's not what causing your timeouts.
Now, conditions come in two types: static and dynamic. Static conditions are just a symlink to the reconf
file, while dynamic conditions are managed by a plugin that's responsible for stepping the "configuration generation" (numeric value in reconf
) and signaling Finit etc. A dynamic condition can be set, and cleared but also in flux. Flux is the state in between configuration changes (generations)
The user conditions set with initctl
are static, essentially initctl cond [set | clear]
are wrappers for ln
and rm
:
root@anarchy:~# initctl cond set foo
root@anarchy:~# ls -l /run/finit/cond/usr/
total 0
lrwxrwxrwx 1 root root 26 May 8 12:02 foo -> /var/run/finit/cond/reconf
Note: the initctl cond [status | dump]
do connect to Finit to decorate the output with owners/asserters/origin of conditions.
So if I wanted to have my own script that is run by mdevd for example to handle create/teardown of a static condition, could I do this?
mkdir -p "/run/finit/dev/ttyUSB2"
echo "1" > "/run/finit/dev/ttyUSB2/exist"
and for off
mkdir -p "/run/finit/dev/ttyUSB2"
echo "0" > "/run/finit/dev/ttyUSB2/exist"
and for flux
mkdir -p "/run/finit/dev/ttyUSB2"
echo "2" > "/run/finit/dev/ttyUSB2/exist"
I am currently doing this in user conditions but it's getting a bit polluted, so I'd rather have a very clear definition of it.
No, the 0, 1, 2 are configuration generations, not state numbers. Also I'm not sure you need the flux state, supporting that is quite a bit more involved and nothing I recommend trying to do outside of the plugin world -- and not before I've documented it fully (lot's of booby traps). Sorry for not being clear on this.
What you can do, however, is static conditions. First of all, they need to be in the cond subdirectory and be a symlink back to reconf, as I mentioned above.
root@zero:/run/finit/cond# mkdir dev
root@zero:/run/finit/cond# mkdir dev/ttyUSB1
root@zero:/run/finit/cond# ln -s /var/run/finit/cond/reconf dev/ttyUSB1/exist
root@zero:/run/finit/cond# initctl -p cond dump
PID IDENT STATUS CONDITION
===================================================
1 init on <dev/ttyUSB1/exist>
...
Removing the symlink removes the condition.
I was able to work around this by using mdevd scripts so it's less pressing, however I do think that adds extra complexity that might actually be a great match with finit as a core feature.
Systemd does this (obviously we don't want to replicate all the features of that beast), but many services do have a dependency on devices being available or not. And since finit runs the earliest and is keeping track of a few dev devices already (primarily networking).
Some usecases for example:
Many well behaved services will poll their device for availability and handle ones that become unavailable, but in some cases it might be better if they are not running at all.
These are all pretty valid use cases where you want a device to be up before finit starts the service.
OK, I'll have a look at it. If we limit the scope to just <dev/foo>
and <dev/bar/baz>
we can copy the pidfile plugin and create a new class of conditions, but it would be based entirely on inotify and not the kernel plug events. Additionally, conditions are constrained to only work properly outside of runlevel S, 6, and 0, i.e. not guaranteed to work at bootstrap or shutdown. Would that be OK with you?
Yup! I think that would work nicely.
Great, thanks! I'll see what I can do.
There, finally, a bare-bones <dev/foo>
and <dev/bar/baz>
monitor in place. No new configure flags, built-in and enabled by default. Documentation to be updated shortly.
I've got a service for gpsd, I want to ensure that /dev/ttyUSB1 exists as a condition before this service will run.
I notice that there is
<net/<DEVICE>/exists>
but no<dev/<DEVICE>/exists>
. I am hoping to have a condition like <dev/ttyUSB1/exists> as a condition for gpsd. Is this possible?As an aside, how about a generic file or directory exists condition, e.g. file//exists ? That could probably work for a device too.