From a8b113185dba0bd3b9384d25a5a2dfe0a9268cee Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 9 Feb 2021 20:20:52 +0100 Subject: [PATCH] Major change, rename conditions to conditions The condition was created to synchronize starting services, hence the abbreviation. Example: the Quagga ripd needs to start after the zebra daemon to ensure its UNIX domain socket is active, otherwise events may be lost. However, considering that synchronization was implemented with UNIX PID files, e.g. waiting for /var/run/quagga/zebra.pid to be created, the condition abbreviation name was hard to understand by most newcomers to Finit. To make matters worse, a new feature to track or even create PID files for services that don't create one themselves, using the syntax 'pid:/path/to/foo.pid' was added. Connecting the dots between these wasn't obvious. This patch renames service conditions pid conditions and also adds a compatibility wrapper to the Finit .conf parser. Any condition given in old .conf files with 'svc/' prefix are internally renamed 'pid/', along with a LOG_INFO notice in syslog. Signed-off-by: Joachim Wiberg --- README.md | 4 ++-- contrib/alpine/finit.d/available/acpid.conf | 2 +- contrib/alpine/finit.d/available/crond.conf | 2 +- contrib/alpine/finit.d/available/klogd.conf | 2 +- contrib/alpine/finit.d/available/ntpd.conf | 2 +- contrib/debian/finit.d/available/acpid.conf | 2 +- contrib/void/finit.d/available/crond.conf | 2 +- contrib/void/finit.d/available/klogd.conf | 2 +- contrib/void/finit.d/available/ntpd.conf | 2 +- doc/conditions.md | 20 ++++++++--------- doc/config.md | 4 ++-- plugins/pidfile.c | 2 +- src/cond-w.c | 25 ++++++++++++--------- src/conf.c | 6 ++++- src/service.c | 2 +- 15 files changed, 43 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 41f958ab..212074e0 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ Here is another example where we instruct Finit to not start BusyBox `ntpd` until `syslogd` has started properly. Finit waits for `syslogd` to create its PID file, by default `/var/run/syslogd.pid`. - service [2345] log /usr/sbin/ntpd -n -N -p pool.ntp.org + service [2345] log /usr/sbin/ntpd -n -N -p pool.ntp.org service [S12345] /sbin/syslogd -n -- Syslog daemon Notice the `log` keyword, BusyBox `ntpd` uses `stderr` for logging when @@ -150,7 +150,7 @@ to the system log daemon using the command line `logger(1)` tool. A service, or task, can have multiple dependencies listed. Here we wait for *both* `syslogd` to have started and basic networking to be up: - service [2345] log /usr/sbin/ntpd -n -N -p pool.ntp.org + service [2345] log /usr/sbin/ntpd -n -N -p pool.ntp.org If either condition fails, e.g. loss of networking, `ntpd` is stopped and as soon as it comes back up again `ntpd` is restarted automatically. diff --git a/contrib/alpine/finit.d/available/acpid.conf b/contrib/alpine/finit.d/available/acpid.conf index 858788df..b86ff909 100644 --- a/contrib/alpine/finit.d/available/acpid.conf +++ b/contrib/alpine/finit.d/available/acpid.conf @@ -1,3 +1,3 @@ # Handle PWR button to shutdown/reboot -- useful in Qemu (virt-manager) # Depends on syslogd having started. Redirect any output to log. -service [2345] log acpid -f -- ACPI daemon +service [2345] log acpid -f -- ACPI daemon diff --git a/contrib/alpine/finit.d/available/crond.conf b/contrib/alpine/finit.d/available/crond.conf index 64410ba4..1ee0538a 100644 --- a/contrib/alpine/finit.d/available/crond.conf +++ b/contrib/alpine/finit.d/available/crond.conf @@ -1 +1 @@ -service [2345] crond -f -S -c /etc/crontabs -- Cron daemon +service [2345] crond -f -S -c /etc/crontabs -- Cron daemon diff --git a/contrib/alpine/finit.d/available/klogd.conf b/contrib/alpine/finit.d/available/klogd.conf index 499d05a8..232f45c5 100644 --- a/contrib/alpine/finit.d/available/klogd.conf +++ b/contrib/alpine/finit.d/available/klogd.conf @@ -1,2 +1,2 @@ # Start klogd as soon as possible, after syslogd, should always run -service [S12345] klogd -n -- Kernel log daemon +service [S12345] klogd -n -- Kernel log daemon diff --git a/contrib/alpine/finit.d/available/ntpd.conf b/contrib/alpine/finit.d/available/ntpd.conf index 9cc7e5d0..1968b000 100644 --- a/contrib/alpine/finit.d/available/ntpd.conf +++ b/contrib/alpine/finit.d/available/ntpd.conf @@ -1,2 +1,2 @@ # Silly Busybox ntpd has no option to use syslog when running in foreground -service [2345] log ntpd -n -N -p pool.ntp.org -- NTP daemon +service [2345] log ntpd -n -N -p pool.ntp.org -- NTP daemon diff --git a/contrib/debian/finit.d/available/acpid.conf b/contrib/debian/finit.d/available/acpid.conf index bfa62ec3..a854b71f 100644 --- a/contrib/debian/finit.d/available/acpid.conf +++ b/contrib/debian/finit.d/available/acpid.conf @@ -1,3 +1,3 @@ # Handle PWR button to shutdown/reboot -- useful in Qemu (virt-manager) # Depends on rsyslogd having started. Redirect any output to log. -service [2345] log acpid -f -- ACPI daemon +service [2345] log acpid -f -- ACPI daemon diff --git a/contrib/void/finit.d/available/crond.conf b/contrib/void/finit.d/available/crond.conf index 9f7cda64..ed1b848d 100644 --- a/contrib/void/finit.d/available/crond.conf +++ b/contrib/void/finit.d/available/crond.conf @@ -1 +1 @@ -service [2345] /usr/sbin/crond -f -S -c /etc/crontabs -- Cron daemon +service [2345] /usr/sbin/crond -f -S -c /etc/crontabs -- Cron daemon diff --git a/contrib/void/finit.d/available/klogd.conf b/contrib/void/finit.d/available/klogd.conf index 7a1f7c5a..9e91c452 100644 --- a/contrib/void/finit.d/available/klogd.conf +++ b/contrib/void/finit.d/available/klogd.conf @@ -1,2 +1,2 @@ # Start klogd as soon as possible, should always run -service [S12345] klogd -n -- Kernel log daemon +service [S12345] klogd -n -- Kernel log daemon diff --git a/contrib/void/finit.d/available/ntpd.conf b/contrib/void/finit.d/available/ntpd.conf index 9cc7e5d0..1968b000 100644 --- a/contrib/void/finit.d/available/ntpd.conf +++ b/contrib/void/finit.d/available/ntpd.conf @@ -1,2 +1,2 @@ # Silly Busybox ntpd has no option to use syslog when running in foreground -service [2345] log ntpd -n -N -p pool.ntp.org -- NTP daemon +service [2345] log ntpd -n -N -p pool.ntp.org -- NTP daemon diff --git a/doc/conditions.md b/doc/conditions.md index f6f1b6ba..a3a47a3e 100644 --- a/doc/conditions.md +++ b/doc/conditions.md @@ -31,11 +31,11 @@ service to run. ### Example ```shell - service [2345] /sbin/netd -- Network monitor + service [2345] /sbin/netd -- Network monitor ``` In this example the Network monitor daemon `netd` is not started until -both the `svc/sbin/setupd` *and* `svc/sbin/zebra` conditions are +both the `pid/sbin/setupd` *and* `pid/sbin/zebra` conditions are satisfied. An `svc` condition is satisfied by the corresponding service's PID file being created. @@ -62,7 +62,7 @@ Built-in Conditions Finit is distributed with a `pidfile` and `netlink` plugin. If enabled, the `pidfile` plugin watches `/var/run/` for PID files created by the -monitored services, and sets a corresponding condition in the `svc/` +monitored services, and sets a corresponding condition in the `pid/` namespace. Similarily, the `netlink` plugin provides basic conditions for when an interface is brought up/down and when a default route (gateway) is set, in the `net/` namespace. @@ -81,7 +81,7 @@ file touched (re-created). Built-in conditions: -- `svc/` +- `pid/` - `net/route/default` - `net//exist` - `net//up` @@ -95,16 +95,16 @@ Built-in conditions: Composition ----------- -The `svc/` conditions can be quite tricky to understand. They are +The `pid/` conditions can be quite tricky to understand. They are generated by the Finit `pidfile.so` plugin and are composed from the daemon's path and the pidfile name (and path). | **service** | **pid:** | **pidfile path** | **svc condition** | |--------------------------------------|-----------------|------------------|-------------------| -| /sbin/foo | | /run/foo.pid | svc/sbin/foo | -| /sbin/bar -p /run/baz.pid | pid:baz | /run/bas.pid | svc/sbin/baz | -| lxc-start -n foo -p /run/lxc/foo.pid | pid:lxc/foo.pid | /run/lxc/foo.pid | svc/lxc/foo | -| /usr/bin/dbus-daemon | pid:dbus/pid | /run/dbus/pid | svc/usr/bin/dbus | +| /sbin/foo | | /run/foo.pid | pid/sbin/foo | +| /sbin/bar -p /run/baz.pid | pid:baz | /run/bas.pid | pid/sbin/baz | +| lxc-start -n foo -p /run/lxc/foo.pid | pid:lxc/foo.pid | /run/lxc/foo.pid | pid/lxc/foo | +| /usr/bin/dbus-daemon | pid:dbus/pid | /run/dbus/pid | pid/usr/bin/dbus | Omitting the `pid:` to run/task/service/sysv stanza means Finit will guess the pidfile path based on `/run/` and the basename(1) of the @@ -128,7 +128,7 @@ conditions that are not satisfied. Listed as `off` below. ~ # initctl cond show PID Service Status Condition (+ on, ~ flux, - off) =============================================================================== - 1419 /sbin/netd on <+svc/sbin/setupd,+svc/sbin/zebra> + 1419 /sbin/netd on <+pid/sbin/setupd,+pid/sbin/zebra> 0 /sbin/udhcpc off <-net/vlan1/exist> ``` diff --git a/doc/config.md b/doc/config.md index 4bd0c3b7..4e4ff69f 100644 --- a/doc/config.md +++ b/doc/config.md @@ -184,7 +184,7 @@ Syntax from forking (daemonizing): ```shell - service [2345] /sbin/ospfd -- OSPF daemon + service [2345] /sbin/ospfd -- OSPF daemon ``` The `[2345]` is the runlevels `ospfd` is allowed to run in, they are @@ -206,7 +206,7 @@ Syntax For example, by adding `pid:/run/foo.pid` to the service `/sbin/bar` that PID file will, not only be created and removed automatically, but also be used by the Finit condition subsystem. So a service/run/task - can depend on ``, notice the composition of conditions. + can depend on ``, notice the composition of conditions. However, if a service `bar` *does* create a PID file, using `foo.pid`, we can inform Finit of this by prepending an `!`: diff --git a/plugins/pidfile.c b/plugins/pidfile.c index 3a1a0d21..afef1008 100644 --- a/plugins/pidfile.c +++ b/plugins/pidfile.c @@ -323,7 +323,7 @@ static struct context pidfile_ctx; * * service /sbin/dropbear ... * - * Which provides the condition, will not be + * Which provides the condition, will not be * set by pidfile.so during `initctl reload` because dropbear is * still SIGSTP:ed waiting for . */ diff --git a/src/cond-w.c b/src/cond-w.c index 3239caa2..df2e135b 100644 --- a/src/cond-w.c +++ b/src/cond-w.c @@ -32,28 +32,31 @@ #include "service.h" /* - * The service condition name is constructed from the 'svc/' prefix, the - * dirname of the svc->cmd, e.g., '/usr/bin/teamd' => 'usr/bin', and the - * service's pid:filename, including an optional subdirectory, without - * the .pid extension. + * The service condition name is constructed from the 'pid/' prefix, + * the dirname of the svc->cmd, e.g., '/usr/bin/teamd' => 'usr/bin', and + * the service's pid:filename, including an optional subdirectory, + * without the .pid extension. * * The following example uses the team (aggregate) service: * * service pid:!/run/teamd/a1.pid /usr/bin/teamd -f /etc/teamd/a1.conf * - * => 'svc/' + 'usr/bin' + 'teamd/a1' => svc/usr/bin/teamd/a1 + * => 'pid/' + 'usr/bin' + 'teamd/a1' => pid/usr/bin/teamd/a1 * * The next example uses the dbus-daemon: * * service pid:!/run/dbus/pid /usr/bin/dbus-daemon * - * => 'svc/' + 'usr/bin' + 'dbus' => svc/usr/bin/dbus + * => 'pid/' + 'usr/bin' + 'dbus' => pid/usr/bin/dbus * * The last example uses lxc-start to start container foo: * * service pid:!/run/lxc/foo.pid lxc-start -n foo -F -p /run/lxc/foo.pid -- Container foo * - * => 'svc/' + '' + 'lxc/foo' => svc/lxc/foo + * => 'pid/' + '' + 'lxc/foo' => pid/lxc/foo + * + * Note: previously the condition ws called 'svc/..', the conf.c parser + * automatically translates to the 'pid/..' prefix and warns. */ char *mkcond(svc_t *svc, char *buf, size_t len) { @@ -81,12 +84,12 @@ char *mkcond(svc_t *svc, char *buf, size_t len) else ptr = rindex(pidfile, '/'); - /* Custom name:foo declaration found => svc/foo instead of /svc/bin/path/pidfile-.pid */ + /* Custom name:foo declaration found => pid/foo instead of /pid/bin/path/pidfile-.pid */ if (strcmp(nm, svc->name)) { - snprintf(buf, len, "svc/%s", svc->name); + snprintf(buf, len, "pid/%s", svc->name); _d("Composed condition from svc->name %s => %s", svc->name, buf); } else { - snprintf(buf, len, "svc%s%s%s", path[0] != 0 && path[0] != '/' ? "/" : "", path, ptr); + snprintf(buf, len, "pid%s%s%s", path[0] != 0 && path[0] != '/' ? "/" : "", path, ptr); _d("Composed condition from cmd %s (path %s) and pidfile %s => %s", svc->cmd, path, ptr, buf); } @@ -306,7 +309,7 @@ static int reassert(const char *fpath, const struct stat *sb, int tflg, struct F /* * Used only by netlink plugin atm. - * type: is a one of svc/, net/, etc. + * type: is a one of pid/, net/, etc. */ void cond_reassert(const char *type) { diff --git a/src/conf.c b/src/conf.c index 4d9c95dc..784161ad 100644 --- a/src/conf.c +++ b/src/conf.c @@ -236,7 +236,11 @@ void conf_parse_cond(svc_t *svc, char *cond) return; } - strlcpy(svc->cond, ptr, sizeof(svc->cond)); + if (!strncmp(ptr, "svc/", 4)) { + snprintf(svc->cond, sizeof(svc->cond), "pid/%s", &ptr[4]); + logit(LOG_INFO, "Migrating cond syntax of %s: %s -> %s", svc->cmd, ptr, svc->cond); + } else + strlcpy(svc->cond, ptr, sizeof(svc->cond)); } struct rlimit_name { diff --git a/src/service.c b/src/service.c index d8379f8e..eb312b40 100644 --- a/src/service.c +++ b/src/service.c @@ -825,7 +825,7 @@ static void parse_cmdline_args(svc_t *svc, char *cmd) * special case when a service is declared with means it does not * support SIGHUP but must be STOP/START'ed at system reconfiguration. * - * Service conditions can be: svc/ for PID files, net//up + * Service conditions can be: pid/ for PID files, net//up * and net//exists. The condition handling is further described * in doc/conditions.md, but worth mentioning here is that the condition * name itself can be modified using the :ID and name:foo syntax.