1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
A RVNIT MANUAL
2022-01-27
Overview
Rvnit is a small but flexible init-system and supervision daemon.
There are three main applications it is designed for:
- As init for a Linux machine
- As init for a Linux container
- As unprivileged supervision daemon
Rvnit is configured by a directory of scripts, defaulting to /etc/rvnit.
In this directory, rvnit looks into executable files (called tasks)
that start with two digits and do not end with ~.
rvnit distinguishes between several kinds of tasks identfied by the
third letter of the file name:
- 'S': startup scripts
- 'K': shutdown scripts
- 'D': daemons
- 'L': loggers
- 'G': global loggers
- 'E': error handlers
Modes of operation
The lifecycle of a machine/container/session using rvnit consists of
three phases.
First, the system is *booted*, by spawning tasks in order from 00 to 99.
This means that for each level 00 to 99:
- startup scripts are run
- daemons are run
- loggers are run, and connected to daemons
- global loggers are run, and connected to the global log
- if a startup script failed, the first error handler of the same or
lower level is run, then the startup script is run again;
if the error handler returns 111, the startup script is skipped.
- the level is finished when all startup scripts ran successfully.
After reaching level 99, the system is in the second phase, the *uptime*.
During uptime, rvnit
- respawns daemons that have exited, but no more than once a second
- responds to commands sent by rvnitctl
- waits for a SIGINT, SIGTERM (containers and non-pid 1 only), Ctrl-Alt-Delete,
or rvnitctl command to start the shutdown
*Shutdown* progresses in levels again, this time from 99 to 00 backwards.
For each level:
- shutdown scripts are run
- daemons are stopped, first by SIGTERM and after 7s by SIGKILL
- loggers are stopped by closing their stdin
Upon reaching level 0, rvnit will poweroff or reboot the machine/container.
Controlling rvnit with rvnitctl
During the uptime of the system, you can remote control rvnit using
the tool rvnitctl.
Usage: rvnitctl [COMMAND] [SERVICE]
Only the first letter of command is relevant, but mnemonic:
- status: show a list of daemons, loggers, and global logger, and
their state, pid, uptime and last exit status.
- up: start SERVICE
- down: stop SERVICE
- p: send signal SIGSTOP to SERVICE
- c: send signal SIGCONT to SERVICE
- h: send signal SIGHUP to SERVICE
- a: send signal SIGALRM to SERVICE
- i: send signal SIGINT to SERVICE
- q: send signal SIGQUIT to SERVICE
- 1: send signal SIGUSR1 to SERVICE
- 2: send signal SIGUSR2 to SERVICE
- t: send signal SIGTERM to SERVICE
- k: send signal SIGKILL to SERVICE
- rescan: re-read /etc/rvnit, start added daemons, stop removed daemons
- Shutdown: shutdown (poweroff) the system
- Reboot: reboot the system
Logging with rvnit
Rvnit distinguishes two kinds of logging mechanism:
- Loggers are associated to one daemon and get the daemon stdout as stdin.
This is a 1:1 correspondence between daemons and loggers, and they must
be named exactly the same, except one has a 'D' and one a 'L'.
Rvnit keeps the pipes between daemons and loggers open and can
respawn daemons and loggers without loss of data.
- The global logger gets logs from all tasks that don't have a custom logger,
as well as rvnit's own log output.
Rvnit keeps a global log pipe and associates logged lines with their
origin pid and time. This pipe is written to even before the global
logger is started, so the global logger will get all messages since
boot time.
Rvnit as init for Linux
Rvnit is self-contained and can be booted directly as pid 1.
It will mount /dev and /run when required, everything else
is left to startup scripts.
When receiving Ctrl-Alt-Delete, rvnit triggers an orderly reboot.
Rvnit as init for a Docker container
Fresh binary releases are provided in Alpine containers at
https://hub.docker.com/r/leahneukirchen/rvnit/tags
rvnit is compiled statically, so you can copy it out if you have
different needs:
COPY --from=docker.io/leahneukirchen/rvnit:latest /bin/rvnit /bin/
CMD ["/bin/rvnit"]
Note that /run must exist in the container if you want to use
the default control socket name.
You can put the control socket onto a bind-mount and remote-control
rvnit using rvnitctl from the outside by pointing RVNIT_SOCK to the
appropriate target.
|