mirror of
https://github.com/troglobit/finit.git
synced 2026-10-27 12:20:54 +00:00
Initial support for templating and instantiating services
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
1 parent
334d4a708a
commit
700c32fd73
5 files changed
+137
-11
No files matched your search
@@ -41,6 +41,7 @@ Features include:
|
|||||||
startup, support for systemd [sd_notify()][], or [s6 style][] too
|
startup, support for systemd [sd_notify()][], or [s6 style][] too
|
||||||
* Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes)
|
* Limited support for [tmpfiles.d(5)][] (no aging, attributes, or subvolumes)
|
||||||
* Pre/Post script actions
|
* Pre/Post script actions
|
||||||
|
* Rudimentary [templating support](doc/config.md#templating)
|
||||||
* Tooling to enable/disable services
|
* Tooling to enable/disable services
|
||||||
* Built-in getty
|
* Built-in getty
|
||||||
* Built-in watchdog, with support for hand-over to [watchdogd](https://troglobit.com/watchdogd.html)
|
* Built-in watchdog, with support for hand-over to [watchdogd](https://troglobit.com/watchdogd.html)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ Finit Configuration
|
|||||||
* [Service Environment](#service-environment)
|
* [Service Environment](#service-environment)
|
||||||
* [Service Synchronization](#service-synchronization)
|
* [Service Synchronization](#service-synchronization)
|
||||||
* [Service Wrapper Scripts](#service-wrapper-scripts)
|
* [Service Wrapper Scripts](#service-wrapper-scripts)
|
||||||
|
* [Templating](#templating)
|
||||||
* [Cgroups](#cgroups)
|
* [Cgroups](#cgroups)
|
||||||
* [Configuration File Syntax](#configuration-file-syntax)
|
* [Configuration File Syntax](#configuration-file-syntax)
|
||||||
* [Hostname](#hostname)
|
* [Hostname](#hostname)
|
||||||
@@ -353,6 +354,26 @@ example employs a wrapper script in `/etc/start.d`.
|
|||||||
> instead of sending SIGHUP at restart/reload events.
|
> instead of sending SIGHUP at restart/reload events.
|
||||||
|
|
||||||
|
|
||||||
|
Templating
|
||||||
|
----------
|
||||||
|
|
||||||
|
Finit comes with rudimentary support for templating, similar to that of
|
||||||
|
systemd. Best illustrated with an example:
|
||||||
|
|
||||||
|
$ initctl show avahi-autoipd@
|
||||||
|
service :%i avahi-autoipd --syslog %i -- ZeroConf for %i
|
||||||
|
|
||||||
|
To enable ZeroConf for, e.g., eth0, use
|
||||||
|
|
||||||
|
$ initctl enable avahi-autoipd@eth0.conf
|
||||||
|
|
||||||
|
The enabled symlink will be set up to avahi-autoipd@.conf and every in‐
|
||||||
|
stance of %i will in the instantiated directive be replaced with eth0.
|
||||||
|
Inspect the result with:
|
||||||
|
|
||||||
|
$ initctl status avahi-autoipd:eth0
|
||||||
|
|
||||||
|
|
||||||
Cgroups
|
Cgroups
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|||||||
+28
-2
@@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.Dd Apr 22, 2023
|
.Dd Apr 24, 2023
|
||||||
.Dt FINIT.CONF 5 SMM
|
.Dt FINIT.CONF 5 SMM
|
||||||
.Os Linux
|
.Os Linux
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -325,9 +325,10 @@ service notify:s6 mdevd -C -O 4 -D %n
|
|||||||
When a service is ready, either by Finit detecting its PID file, or
|
When a service is ready, either by Finit detecting its PID file, or
|
||||||
their respective readiness mechanism has been triggered, Finit creates
|
their respective readiness mechanism has been triggered, Finit creates
|
||||||
then service's ready condition which other services can depend on:
|
then service's ready condition which other services can depend on:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
$ initctl -v cond get service/mdevd/ready
|
$ initctl -v cond get service/mdevd/ready
|
||||||
on
|
on
|
||||||
|
.Ed
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
If a service should not be automatically started, it can be configured
|
If a service should not be automatically started, it can be configured
|
||||||
@@ -818,6 +819,31 @@ the example sets
|
|||||||
to denote that it doesn't support SIGHUP. That way Finit will
|
to denote that it doesn't support SIGHUP. That way Finit will
|
||||||
stop/start the service instead of sending SIGHUP at restart/reload
|
stop/start the service instead of sending SIGHUP at restart/reload
|
||||||
events.
|
events.
|
||||||
|
.Sh TEMPLATING
|
||||||
|
Finit comes with rudimentary support for templating, similar to that of
|
||||||
|
systemd. Best illustrated with an example:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
$ initctl show avahi-autoipd@
|
||||||
|
service :%i avahi-autoipd --syslog %i -- ZeroConf for %i
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
To enable ZeroConf for, e.g.,
|
||||||
|
.Cm eth0 ,
|
||||||
|
use
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
$ initctl enable avahi-autoipd@eth0.conf
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
The enabled symlink will be set up to
|
||||||
|
.Cm avahi-autoipd@.conf
|
||||||
|
and every instance of
|
||||||
|
.Cm %i
|
||||||
|
will in the instantiated directive be replaced with
|
||||||
|
.Cm eth0 .
|
||||||
|
Inspect the result with:
|
||||||
|
.Bd -unfilled -offset indent
|
||||||
|
$ initctl status avahi-autoipd:eth0
|
||||||
|
.Ed
|
||||||
.Sh CGROUPS
|
.Sh CGROUPS
|
||||||
There are three major cgroup configuration directives:
|
There are three major cgroup configuration directives:
|
||||||
.Pp
|
.Pp
|
||||||
|
|||||||
+71
-1
@@ -914,11 +914,79 @@ static int parse_dynamic(char *line, struct rlimit rlimit[], char *file)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Very simple and crude implementation, only supports '%i'
|
||||||
|
*/
|
||||||
|
static char *instantiate(char *line, char *name)
|
||||||
|
{
|
||||||
|
char *ptr, *end = strchr(line, 0);
|
||||||
|
char *pos = line;
|
||||||
|
size_t num = 0;
|
||||||
|
|
||||||
|
if (!name[0] || !end)
|
||||||
|
return line;
|
||||||
|
|
||||||
|
while ((ptr = strchr(pos, '%'))) {
|
||||||
|
num++;
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = realloc(line, strlen(line) + num * strlen(name) + 1);
|
||||||
|
if (!ptr)
|
||||||
|
return line;
|
||||||
|
|
||||||
|
pos = line = ptr;
|
||||||
|
while ((ptr = strchr(pos, '%'))) {
|
||||||
|
if (!strncmp(ptr, "%i", 2)) {
|
||||||
|
char *rest = &ptr[2];
|
||||||
|
char *next = ptr + strlen(name);
|
||||||
|
|
||||||
|
memmove(next, rest, strlen(rest) + 1);
|
||||||
|
memcpy(ptr, name, strlen(name));
|
||||||
|
|
||||||
|
pos += strlen(name);
|
||||||
|
} else
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_template(const char *file, char *name, size_t len)
|
||||||
|
{
|
||||||
|
char *ptr, *nm;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
ptr = strchr(file, '@');
|
||||||
|
if (!ptr)
|
||||||
|
return 0; /* not a template */
|
||||||
|
|
||||||
|
nm = ptr + 1;
|
||||||
|
ptr = strstr(nm, ".conf");
|
||||||
|
if (!strcmp(nm, ".conf") || !ptr)
|
||||||
|
return 1; /* template itself or invalid */
|
||||||
|
|
||||||
|
while (nm < ptr && i < len - 1)
|
||||||
|
name[i++] = *nm++;
|
||||||
|
name[i] = 0;
|
||||||
|
|
||||||
|
return 1; /* instantiated template */
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_conf(char *file, int is_rcsd)
|
static int parse_conf(char *file, int is_rcsd)
|
||||||
{
|
{
|
||||||
struct rlimit rlimit[RLIMIT_NLIMITS];
|
struct rlimit rlimit[RLIMIT_NLIMITS];
|
||||||
|
char name[65] = { 0 };
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
|
if (is_template(file, name, sizeof(name))) {
|
||||||
|
if (!name[0]) {
|
||||||
|
dbg("*** Skipping template file %s", file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
dbg("*** instantiating %s from %s ...", name, file);
|
||||||
|
}
|
||||||
|
|
||||||
fp = fopen(file, "r");
|
fp = fopen(file, "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -938,7 +1006,9 @@ static int parse_conf(char *file, int is_rcsd)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
tabstospaces(line);
|
tabstospaces(line);
|
||||||
// dbg("%s", line);
|
// dbg("raw: %s", line);
|
||||||
|
line = instantiate(line, name);
|
||||||
|
// dbg("ins: %s", line);
|
||||||
|
|
||||||
if (!parse_static(line, is_rcsd))
|
if (!parse_static(line, is_rcsd))
|
||||||
;
|
;
|
||||||
|
|||||||
+16
-8
@@ -253,18 +253,18 @@ static char *conf(char *path, size_t len, char *name, int creat)
|
|||||||
|
|
||||||
int serv_enable(char *arg)
|
int serv_enable(char *arg)
|
||||||
{
|
{
|
||||||
|
char src[strlen(arg) + 6];
|
||||||
size_t arglen, len;
|
size_t arglen, len;
|
||||||
char corr[40];
|
char *ptr;
|
||||||
|
|
||||||
if (!arg || !arg[0]) {
|
if (!arg || !arg[0]) {
|
||||||
WARNX("missing argument to enable, may be one of:");
|
WARNX("missing argument to enable, may be one of:");
|
||||||
return serv_list("available");
|
return serv_list("available");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strstr(arg, ".conf")) {
|
strlcpy(src, arg, sizeof(src));
|
||||||
snprintf(corr, sizeof(corr), "%s.conf", arg);
|
if (!strstr(src, ".conf"))
|
||||||
arg = corr;
|
strlcat(src, ".conf", sizeof(src));
|
||||||
}
|
|
||||||
|
|
||||||
if (chdir(finit_rcsd))
|
if (chdir(finit_rcsd))
|
||||||
ERR(72, "failed cd %s", finit_rcsd);
|
ERR(72, "failed cd %s", finit_rcsd);
|
||||||
@@ -272,13 +272,21 @@ int serv_enable(char *arg)
|
|||||||
if (icreate && mkdir("enabled", 0755) && EEXIST != errno)
|
if (icreate && mkdir("enabled", 0755) && EEXIST != errno)
|
||||||
ERR(73, "failed creating %s/enabled directory", finit_rcsd);
|
ERR(73, "failed creating %s/enabled directory", finit_rcsd);
|
||||||
|
|
||||||
len = snprintf(NULL, 0, "%s/available/%s", finit_rcsd, arg);
|
len = snprintf(NULL, 0, "%s/available/%s", finit_rcsd, src);
|
||||||
arglen = snprintf(NULL, 0, "%s/enabled/%s", finit_rcsd, arg);
|
arglen = snprintf(NULL, 0, "%s/enabled/%s", finit_rcsd, arg);
|
||||||
char argpath[arglen + 1], path[len + 1];
|
char argpath[arglen + 1], path[len + 1];
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/available/%s", finit_rcsd, arg);
|
snprintf(path, sizeof(path), "%s/available/%s", finit_rcsd, src);
|
||||||
|
|
||||||
|
/* check for template instatiation */
|
||||||
|
ptr = strchr(path, '@');
|
||||||
|
if (ptr++) {
|
||||||
|
*ptr = 0;
|
||||||
|
strlcat(path, ".conf", sizeof(path));
|
||||||
|
}
|
||||||
|
|
||||||
if (!fexist(path))
|
if (!fexist(path))
|
||||||
ERRX(72, "cannot find %s", path);
|
ERRX(72, "cannot find %s%s", ptr ? "template ": "", path);
|
||||||
|
|
||||||
snprintf(argpath, sizeof(argpath), "%s/enabled/%s", finit_rcsd, arg);
|
snprintf(argpath, sizeof(argpath), "%s/enabled/%s", finit_rcsd, arg);
|
||||||
if (fexist(argpath))
|
if (fexist(argpath))
|
||||||
|
|||||||
Reference in new issue
Block a user