Git Product home page Git Product logo

dinit's Introduction

Dinit

v0.18.1pre (beta)


Dinit logo

This is the README for Dinit, the service manager and init system. It is intended to provide an overview; For full documentation please check the manual pages. The impatient may wish to check out the getting started guide.

Dinit is used as the init system for Chimera Linux, and is an init system option for Artix Linux.


Dinit is free software. You may wish to consider sponsoring Dinit's development.


Contents

  1. Introduction
    1. Features
    2. Target platforms
    3. Other information
  2. Reporting issues
  3. Configuring services
    1. Service types
    2. Service description files
  4. Running Dinit
  5. Controlling services
    1. Service hierarchy and states
    2. Using dinitctl

Introduction

Dinit is a service supervisor with dependency support which can also act as the system "init" program. It was created with the intention of providing a portable init system with dependency management, that was functionally superior to many extant inits. Development goals include clean design, robustness, portability, usability, and avoiding feature bloat (whilst still handling common - and some less-common - use cases). Dinit is designed to integrate with rather than subsume or replace other system software.

Features

Dinit can launch multiple services in parallel, with dependency management (i.e. if one service's operation depends on another, the latter service will be started first). It can monitor the process corresponding to a service, and re-start it if it dies, and it can do this in an intelligent way - first "rolling back" all dependent services, and restarting them when their dependencies are satisfied. The dinitctl tool can be used to start or stop services and check their state.

Dinit is designed to run as either as a system service manager (runs as root, uses system paths for configuration) or a user process (runs as a user, uses paths in the user's home directory for configuration).

Target platforms

Dinit is designed to work on POSIXy operating systems such as Linux and OpenBSD. It is written in C++ and uses the Dasynq event handling library, which was written especially to support Dinit. (Note that a copy of Dasynq is bundled with Dinit, so a separate copy is not required for compilation; however, the bundled copy does not include the documentation or test suite).

Other information

See doc/COMPARISON for a comparison of Dinit with similar software packages.

Dinit is licensed under the Apache License, version 2.0. A copy of this license can be found in the LICENSE file.

This software was written by Davin McCall [email protected] with contributions from many others. See CONTRIBUTORS.

See BUILD for information on how to build Dinit. See the doc directory for information on design, code style, guidelines for contributions, and end-user-oriented documentation.

Full documentation for Dinit is available in the form of manual (man) pages:

  • dinit(8) - the dinit daemon
  • dinit-service(5) - service description format and service settings
  • dinitctl(8) - dinitctl, a utility to control the dinit daemon and manage services
  • dinitcheck(8) - dinitcheck, a utility to check service descriptions for errors/lint
  • dinit-monitor(8) - dinit-monitor, a utility to monitor a service and run a command when service state changes

A brief guide to some basic usage is included in the latter part of this README.

Reporting issues

Please use Github issues to report bugs, and provide as much information as is necessary to reliably reproduce the issue.

Please do not file feature requests unless you are working on system integration (eg. you are a package maintainer for a distribution that supports Dinit, or you are working to provide Dinit support for a particular distribution) and need to solve a real problem, or unless you are willing to provide patches (in this case you can open an issue for discussion - in which case please also see the CONTRIBUTING file).

Configuring services

This section and the following sections are intended as an introductory guide, and to give a feel for what using Dinit is like. For a complete reference, see the man pages: dinit(8) and dinit-service(5).

Service types

A "service" is nominally a persistent process or system state. The two main types of service are a process service (represented by a an actual process) and a scripted service (which is started and stopped by running a process - often a shell script - to completion). There are also bgprocess services and internal services. See the dinit-service(5) manual page for details.

Many programs that you might want to run under Dinit's supervision can run either "in the foreground" or as a daemon ("in the background"), and the choice is dictated by a command line switch (for instance the -D and -F switches to Samba's "smbd"). Although it might seem counterintuitive, the "foreground" mode should be used for programs registered as process services in Dinit; this allows Dinit to monitor the process.

Service description files

Dinit discovers services by reading service description files. These files reside in a directory (/etc/dinit.d is the default "system" location, with /usr/local/lib/dinit.d and /lib/dinit.d also searched; the default user location is $HOME/.config/dinit.d) and the name of a service description file matches the name of the service it configures.

For example, a service named "mysql" might be configured via the service description file named /etc/dinit.d/mysql. Service descriptions are loaded lazily, as needed by Dinit; so, this service description file will usually be read when the mysql service is first started.

(An example of a complete set of system service descriptions can be found in the doc/linux/services directory).

A service description file has a textual format and consists of a number of parameter settings. Some examples of the available parameters are:

type = process | bgprocess | scripted | internal
command = ...
stop-command = ...
run-as = (user-id)
restart = (boolean)
logfile = ...
pid-file = ...
options = ...
depends-on = (service name)
depends-ms = (service name)
waits-for = (service name)

Typically, a service which runs as a process will use the command setting, and include a waits-for dependency on a number of other services (to ensure that the system is ready for general operation). For example, a service description for sshd might look like the following:

type = process
command = /usr/sbin/sshd -D
waits-for = syslogd
depends-on = loginready

In this example, syslogd and loginready are also services (which must have their own service descriptions).

A wide range of service settings and options are available. Please see the manual page for a full list.

Running Dinit

The main Dinit executable is called dinit.

Dinit can run as the system "init" - the first process started by the kernel on boot - which is normally done by linking or copying dinit to /sbin/init. This is currently supported only on Linux. It requires having suitable service descriptions in place and should be attempted only by those comfortable with low-level system administration and recovery. See doc/linux directory for more information.

Dinit can also run as a normal process, and can be started in this case by a regular user.

By default, regardless of whether it runs as a system or user process, Dinit will look for and start the service named "boot". This service should be configured with dependencies which will cause any other desired services to start. You can specify alternative services to start via the dinit command line (consult the manual page for more information).

Controlling services

Service hierarchy and states

Services can depend on other services for operation, and so form a dependency hierarchy. Starting a service which depends on another causes that other service to start (and the first service waits until the latter has started before its process is launched and it is itself considered started).

Services are considered active when they are not stopped. Services can also be explicitly marked as active (this normally happens when you explicitly start a service). Finally, a service with an active dependent is also considered active.

If a service stops and becomes inactive (i.e. it is not explicitly marked active and has no active dependents) then any services it depends on will also be stopped (becoming inactive) unless they have other active dependents, or they were explicitly started and marked active.

What this means is that, in general, starting an (inactive, stopped) service and then stopping it will return the system to its prior state - no dependencies which were started automatically will be left running.

Using dinitctl

You can use the "dinitctl" utility to start and stop services. Typical invocations are:

dinitctl start <service-name>
dinitctl stop <service-name>
dinitctl release <service-name>
dinitctl status <service-name>
dinitctl list

Note that a start marks the service active, as well as starting it if it is not already started; the opposite of this is actually release, which clears the active mark and stops it if it has no active dependent services.

The stop command by default acts as a release that also causes the service to stop. If stopping a service would also require a dependent service to stop, a warning will be issued; the --force option will be required to bypass the warning, though it is generally advisable to stop the dependent systems manually one-by-one - indirectly force-stopping the boot service may cause every service to stop, ending user sessions!

When run as root, dinitctl (by default) communicates with the system instance of dinit. Otherwise, it communicates with a user (personal) instance. This can be overridden (using -u or -s for the user or system instance, respectively), but note that regular users will generally lack the required permission to communicate with the system instance, which is intended to be controlled only by the root user.

Here is an example command for starting a service:

dinitctl start mysql   # start mysql service

You can "pin" a service in either the stopped or started state, which prevents it from changing state either due to a dependency/dependent or a direct command:

dinitctl start --pin mysql  # start mysql service, pin it as "started"
dinitctl stop mysql  # removes activation, service doesn't stop due to pin
dinitctl unpin mysql # release pin; service will now stop

You can pin a service in the stopped state in order to make sure it doesn't get started accidentally (either via a dependency or directly) when you are performing administration or maintenance.

Check the state of an individual service using the "status" subcommand:

dinitctl status mysql

The output will tell you the current service state; for a running service, it may look something like the following:

Service: mysql
    State: STARTED
    Activation: explicitly started
    Process ID: 3393

Finally, you can list the state of all loaded services:

dinitctl list

This may result in something like the following:

[[+]     ] boot
[{+}     ] tty1 (pid: 300)
[{+}     ] tty2 (pid: 301)
[{+}     ] tty3 (pid: 302)
[{+}     ] tty4 (pid: 303)
[{+}     ] loginready (has console)
[{+}     ] rcboot
[{+}     ] filesystems
[{+}     ] udevd (pid: 4)
[     {-}] mysql

The above represents a number of started services and one stopped service (mysql). Only the boot service is marked active ([+] rather than {+}); all other services are running only because they are (directly or indirectly) dependencies of boot. Services transitioning state (starting or stopping) are displayed with an arrow indicating the transition direction:

[[ ]<<   ] mysql     # starting (and marked active)
[   >>{ }] mysql     # stopping

The brackets indicate the target state, which may not be the state to which the service is currently transitioning. For example:

[   <<{ }] mysql     # starting, but will stop after starting
[{ }>>   ] mysql     # stopping, but will restart once stopped

Remember that a starting service may be waiting for its dependencies to start, and a stopping service may be waiting for its dependencies to stop.

For a complete summary of dinitctl command line options, use:

dinitctl --help

Or, for more detailed help, check the manual page for dinitctl.

dinit's People

Contributors

amano-kenji avatar asherikov avatar capezotte avatar davmac314 avatar dependabot[bot] avatar duncaen avatar firasuke avatar fpoussin avatar iacore avatar ingwiephoenix avatar into-the-v0id avatar james-knippes avatar konimex avatar mobin-2008 avatar mskarbek avatar q66 avatar realroot2185 avatar roze061 avatar travankor avatar vext01 avatar yukarichiba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dinit's Issues

Possible dinitcheck dependency resolution failure (0.8.0)

Report from user; dinitcheck is not finding all dependencies:

> dinitctl list     
[{+}     ] boot
[{+}     ] mail-loop (pid: 53615)
[{+}     ] syncthing (pid: 89252)
[{+}     ] mpd (pid: 28838)
> dinitcheck        
Checking service: boot...
Checking service: mpd...
No problems found.

Dependencies from list should all be found:

> cat boot           
type = internal
waits-for.d = /home/edd/.dinit
> ls -1 /home/edd/.dinit
mail-loop
mpd
syncthing

Additional:

> cat mail-loop 
type = process
command = /home/edd/eck2/bin/mail-loop
termsignal = KILL
>
> cat mpd
type = process
command = /usr/local/bin/mpd --no-daemon
>
> cat syncthing 
type = process
command = /usr/local/bin/syncthing -no-browser -logfile=/tmp/stlog

integration testing

What is your take on 'integration testing' scenario, i.e., the situation when service crashes must not be recoverable. For example, diinit could start some sort of crash handler service on failure or terminate everything including itself. It looks like depends-on is an option, but there is no depends-on.d, which is quite inconvenient. It would also be interesting to set default service parameters depending on scenario (testing/production) via service templates.

[RFE] Redirect stdout/stderr for all services

Currently, only one service is able to print to the console, the rest is expected to use some kind of logging management (rsyslog for example). It is perfectly valid and makes sense in a bare metal/VM scenario but falls apart in containers context. It would be very beneficial for containers use case to be able to redirect stdout/stderr of all running services to console and let a container runtime manage the logs.

Command naming

The names looks like systemd commands with the "ctl" suffix. Totally distinctive names will avoid any confusion. Especially if the project is made in reaction of systemd.

load-options and environment variables

Description

I've been reading the docs about load-options, and I'm a bit confused of what and how environment variables are read. The code has env-file option, but there's no documentation on dinit-service(5). I'm using a test scripted service with GNU Hello to see how load-options work, with its output piped to /run/hello.log. However, when I start the service, /run/hello.log has no contents at all, when it should've been greet1 as per addendum.

Addenda

Contents of /etc/dinit.d/hello

type = scripted
command = /usr/bin/hello -g $GREET
logfile = /run/hello.log
load-options = sub-vars
env-file = /etc/hello.conf

Contents of hello.conf

GREET="greet1"

notify-send support

It would be neat if dinit could send desktop notifications when run in user mode. For example, when a service fails, or restarts.

dinit readiness notification support

I was wondering if you'd be interested in having support for readiness notification of dinit itself, in a similar manner to how it handles it for services themselves, I was thinking something like having a launch parameter to pass a file descriptor number to which dinit would write after finishing startup of its initial services (boot or the ones passed on command line).

My use case for this is for dinit-userservd, which is Chimera's daemon that automatically manages user instances of dinit while keeping track of logins/logouts (via a PAM module; the PAM module connects to the daemon's socket, which is considered a login, and disconnection is considered a logout).

Right now I have a bit clunky mechanism in place - the daemon generates the boot service it starts dinit with, which then does startup of user services (your custom boot.d which lives in your home directory), and the daemon itself basically creates a named pipe, while the generated boot service pokes the write end of that pipe, which then signals the daemon and the daemon allows the login to proceed on PAM side.

If I was able to specify the file descriptor and the readiness was handled in dinit itself, I would be able to create a local unnamed pipe in-process and pass the write end to dinit (since it's a child process) and otherwise keep things the same (just without having to touch the filesystem).

I was going to implement this, but I first wanted to know your opinion and/or if you have any better ideas.

bgprocess fails to read pid-file

dinit fails to read pid file:

dinit: cntlm: read pid file: No such file or directory
[FAILED] cntlm
[  OK  ] boot
cntlm[11]: Daemon ready

Process is working correctly and creates pid file in the right place but I suspect that dinit tries to read it too soon.
Service file:

type = bgprocess
command = /usr/sbin/cntlm -c /etc/cntlm.conf -U cntlm -P /run/cntlm/cntlmd.pid
pid-file = /run/cntlm/cntlmd.pid
restart = true
smooth-recovery = true
options = runs-on-console
depends-on = cntlm-config

Failed to build with GCC 10

With GCC 8.3 dinit 0.8.2 compiles just fine and all tests passed but with GCC 10.1:

g++ -D_GLIBCXX_USE_CXX11_ABI=1 -std=c++11 -Os -Wall -fno-rtti -fno-plt -flto -MMD -MP -Iincludes -Idasynq -c proc-service.cc -o proc-service.o
In file included from dasynq/dasynq.h:7,
                 from includes/dinit.h:4,
                 from proc-service.cc:7:
dasynq/dasynq-stableheap.h:21:5: error: 'uint64_t' does not name a type; did you mean 'u_int64_t'?
   21 |     uint64_t order;
      |     ^~~~~~~~
      |     u_int64_t
dasynq/dasynq-stableheap.h:24:25: error: expected ')' before 'o'
   24 |     stable_prio(uint64_t o, U... u) : p(u...), order(o)
      |                ~        ^~
      |                         )
dasynq/dasynq-stableheap.h:62:5: error: 'uint64_t' does not name a type; did you mean 'u_int64_t'?
   62 |     uint64_t sequence = 0;
      |     ^~~~~~~~
      |     u_int64_t
dasynq/dasynq-stableheap.h: In member function 'bool dasynq::stable_heap<H, T, P, C>::insert(dasynq::stable_heap<H, T, P, C>::handle_t&, P)':
dasynq/dasynq-stableheap.h:71:34: error: 'sequence' was not declared in this scope
   71 |         auto sp = stable_prio<P>(sequence++, pval);
      |                                  ^~~~~~~~
dasynq/dasynq-stableheap.h: In instantiation of 'bool dasynq::compare_stable_prio<P, C>::operator()(const dasynq::stable_prio<P>&, const dasynq::stable_prio<P>&) [with P = int; C = std::less<int>]':
dasynq/dasynq-daryheap.h:165:23:   required from 'void dasynq::dary_heap<T, P, Compare, N>::bubble_up(dasynq::dary_heap<T, P, Compare, N>::hindex_t, dasynq::dary_heap<T, P, Compare, N>::handle_t&, const P&) [with T = dasynq::dprivate::empty_node; P = dasynq::stable_prio<int>; Compare = dasynq::compare_stable_prio<int, std::less<int> >; int N = 4; dasynq::dary_heap<T, P, Compare, N>::hindex_t = long unsigned int]'
dasynq/dasynq-daryheap.h:188:22:   required from 'void dasynq::dary_heap<T, P, Compare, N>::remove_h(dasynq::dary_heap<T, P, Compare, N>::hindex_t) [with T = dasynq::dprivate::empty_node; P = dasynq::stable_prio<int>; Compare = dasynq::compare_stable_prio<int, std::less<int> >; int N = 4; dasynq::dary_heap<T, P, Compare, N>::hindex_t = long unsigned int]'
dasynq/dasynq-daryheap.h:280:9:   required from 'void dasynq::dary_heap<T, P, Compare, N>::remove(dasynq::dary_heap<T, P, Compare, N>::handle_t&) [with T = dasynq::dprivate::empty_node; P = dasynq::stable_prio<int>; Compare = dasynq::compare_stable_prio<int, std::less<int> >; int N = 4]'
dasynq/dasynq-stableheap.h:112:21:   required from 'void dasynq::stable_heap<H, T, P, C>::remove(dasynq::stable_heap<H, T, P, C>::handle_t_r) [with H = dasynq::dprivate::dary_heap_def; T = dasynq::dprivate::empty_node; P = int; C = std::less<int>; dasynq::stable_heap<H, T, P, C>::handle_t_r = dasynq::dary_heap<dasynq::dprivate::empty_node, dasynq::stable_prio<int>, dasynq::compare_stable_prio<int, std::less<int> >, 4>::handle_t&]'
dasynq/dasynq.h:453:35:   required from 'void dasynq::dprivate::event_dispatch<Traits, LoopTraits>::dequeue_watcher(dasynq::dprivate::base_watcher*) [with Traits = dasynq::epoll_traits; LoopTraits = dasynq::default_traits<dasynq::null_mutex>]'
dasynq/dasynq.h:1065:34:   required from 'void dasynq::event_loop<T_Mutex, Traits>::dequeue_watcher(dasynq::event_loop<T_Mutex, Traits>::base_watcher*) [with T_Mutex = dasynq::null_mutex; Traits = dasynq::default_traits<dasynq::null_mutex>; dasynq::event_loop<T_Mutex, Traits>::base_watcher = dasynq::dprivate::base_watcher]'
dasynq/dasynq.h:1703:34:   required from 'void dasynq::dprivate::fd_watcher<T_Loop>::set_enabled(dasynq::dprivate::fd_watcher<T_Loop>::event_loop_t&, bool) [with EventLoop = dasynq::event_loop<dasynq::null_mutex>; dasynq::dprivate::fd_watcher<T_Loop>::event_loop_t = dasynq::event_loop<dasynq::null_mutex>]'
proc-service.cc:67:59:   required from here
dasynq/dasynq-stableheap.h:49:18: error: 'const class dasynq::stable_prio<int>' has no member named 'order'
   49 |         return a.order < b.order;
      |                ~~^~~~~
dasynq/dasynq-stableheap.h:49:28: error: 'const class dasynq::stable_prio<int>' has no member named 'order'
   49 |         return a.order < b.order;
      |                          ~~^~~~~
make[1]: *** [Makefile:51: proc-service.o] Error 1

[Feature request] Enable/disable service

I know that what I will propose is a lot like systemd but IMO it's worth considering.
I would like to have separate service configuration dir - /var/lib/dinit.d and be able to enable service by linking services in it to /etc/dinit.d dir. boot service could automatically assume that everything in /etc/dinit.d should be treated as waits-for.
Reasoning behind that is to be able to package service config file with software, install/uninstall and manage that service using simple %post/%preun rpm macros without parsing and editing boot file.

How to load "Specifie" service from bootloader/kernel comand line?

Hello.

We can start the single service using dinit by entering single in the Bootloader command line.
But unfortunately, it is not possible to load another service with this method.
This is important to me because I'm considering replacing the single service with rescue and also want to implement a systemd target-like structure in @Dinit-on-Devuan.
This feature (calling any service using the Bootloader command line) makes it possible to run any target at system startup.

@davmac314 Now my question is whether it is possible to do this or whether such a feature has been implemented or not?

regards

Dinit should diagnose deadlock when a service and its dependency both require console

Simple situation - docker container with 3 services:
crond (/etc/dinit.d/crond ):

type = process
command = /usr/sbin/crond -n -m off
restart = false

confd (/etc/dinit.d/confd):

type = scripted
command = /etc/dinit.d/confd.sh start
restart = false
options = runs-on-console

confd.sh (/etc/dinit.d/confd.sh):

#!/bin/sh

if [ "$1" = start ]; then
    /usr/bin/confd -onetime -backend etcd -node ${ETCD_HOST}
fi

nodejsapp (/etc/dinit.d/nodejsapp)

type = process
command = /usr/bin/node app.js
restart = false
options = runs-on-console
depends-ms = confd
start-timeout = 10

All that run by boot:

type = internal

waits-for = confd
waits-for = crond
waits-for = nodejsapp

Dinit fails to start nodejsapp. Container hangs at:

# docker exec -it nodejsapp bash
# dinitctl -s list
[{ }<<   ] boot
[{+}     ] confd
[{+}     ] crond
[{ }<<   ] nodejsapp

confd successfully finished it's job end exited with 0, crond works fine but nodejsapp never starts:

# docker exec -it nodejsapp bash
# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  13724  3160 ?        Ss   16:32   0:00 /usr/sbin/dinit -s -d /etc/dinit.d
root         8  0.0  0.0  22964  2828 ?        Ss   16:32   0:00 /usr/sbin/crond -n -m off
root        19  0.0  0.0  12124  3188 pts/0    Ss   16:33   0:00 bash
root        49  0.0  0.0  34936  2992 pts/0    R+   16:45   0:00 ps aux

If you exec into container and manually stop and then start nodejsapp then it starts fine and have correct status in dinitctl -s list. start-timeout = 10 seems to have no effect, container just hangs in that state for ever.

before and after support?

it might be handy to be able to specify a constraint that a service has to start before or after (like waits-for but without actually requesting the named service to start, instead only having an effect if the named service is enabled) some other service starts; e.g. like before = foo

this would allow for more flexible handling of ordering when writing service files, without having to touch other service files to get it

`run-as` does not work as advertised

man specifies that run-as will set group to the primary group of the specified user. Unfortunately that doesn't work, for user uid=998(gitlab-runner) gid=995(gitlab-runner) groups=995(gitlab-runner) process with run-as set to gitlab-runner works as gitlab-runner:root.

dinit run as pid 1 (root:root) in container.

[Documentation] Using dinit on LFS/BLFS - could a subsection be added to the main README.md or elsewhere?

Hey Davin,

Not sure if you have time/energy, but it may be interesting to see how to use and apply dinit to a LFS/BLFS setup (linux from scratch / beyond linux from scratch).

E. g. ideally a short recipe how to get that to work, for people who never before used dinit but would like to try it out. Please feel free to close this if this seems too much work or is otherwise not wanted, no problem!

stop-command memory issue

The argv for stop-command is using a string that is later moved, leaving behind an argv (from separate_args) with invalid references to the string.
This specifically happens in my case when the string is <=16 bytes and is stack allocated, apparently any use of the underlying memory would be invalid/undefined after std::move, so just making sure the string is heap allocated is not a full fix.

==6138==    at 0x4D03FD3: __execvpe_common (execvpe.c:75)
==6138==    by 0x1257E2: base_process_service::run_child_proc(run_proc_params) (run-child-proc.cc:336)
==6138==    by 0x11ECF8: base_process_service::start_ps_process(std::vector<char const*, std::allocator<char const*> > const&, bool) (baseproc-service.cc:199)
==6138==    by 0x11CB65: scripted_service::bring_down() (proc-service.cc:800)
==6138==    by 0x110C45: service_set::process_queues() (service.h:916)
==6138==    by 0x11BF6D: scripted_service::handle_exit_status(bp_sys::exit_status) (proc-service.cc:614)
==6138==    by 0x11BA47: service_child_watcher::status_change(dasynq::event_loop<dasynq::null_mutex, dasynq::default_traits<dasynq::null_mutex> >&, int, int) (proc-service.cc:238)
==6138==    by 0x11F3E4: dasynq::dprivate::child_proc_watcher_impl<dasynq::event_loop<dasynq::null_mutex, dasynq::default_traits<dasynq::null_mutex> >, service_child_watcher>::dispatch(void*) (dasynq.h:2216)
==6138==    by 0x112323: dasynq::event_loop<dasynq::null_mutex, dasynq::default_traits<dasynq::null_mutex> >::process_events(int) (dasynq.h:1463)
==6138==    by 0x112BA6: dasynq::event_loop<dasynq::null_mutex, dasynq::default_traits<dasynq::null_mutex> >::run(int) (dasynq.h:1501)
==6138==    by 0x10FE5B: dinit_main(int, char**) (dinit.cc:607)
==6138==    by 0x10E609: main (dinit-main.cc:12)
==6138==  Address 0x1ffefff8e0 is on thread 1's stack
==6138==  912 bytes below stack pointer

make fails with more than one job

make -j tries to build mconfig.h at the same time as other sourcefiles which require mconfig.h.

Adding

$(dinit_objects): includes/mconfig.h

and changing the dinit target to dinit: $(dinit_objects) in src/makefile fixes this problem for me.

make check -j also fails, but i did not look further into this.

[Feature Request] Set-target

Something like dinitctl set-target is needed. Systemd handles this with .target files, so dinit will need to either use another form of .sh files or incorporate .target files.

Current master fails to compile

$ git log -1
commit bd7762913aadb274dd89b92f15c31d0986d6d9c0 (HEAD -> master, origin/master, origin/HEAD)
(...)
$ make
make -C src all
make[1]: Entering directory '/home/marcin.skarbek/projects/dinit/src'
make[1]: *** No rule to make target 'service.h', needed by 'dinit.o'.  Stop.
make[1]: Leaving directory '/home/marcin.skarbek/projects/dinit/src'
make: *** [Makefile:4: all] Error 2

Variable substitution outside command paths

In my system I'm implementing a concept of systemwide user services. For this, having the ability to do some kind of variable substitution in non-command paths (e.g. socket-listen and notably logfile) would be good (e.g. homedir, or current user ID). As far as I can tell there is no way to accomplish this currently.

Security policy

I know it's too early to do that. dinit is currently in version 0.15.1 and due to one of the design principles of dinit "Limited Feature Scope" it is very unlikely that we will encounter security vulnerabilities but again I think it is useful to consider a "Security policy" .
Just specify how to report a security vulnerability (github issues would definitely be a bad idea. I personally recommend email)

This is a marginal issue right now, but I personally think it will be important in the future.

regards

command to export environment variables into activation env

This would be similar to systemd, which provides a way to export environment variables into its activation environment that is then used for services that are started later. I'm thinking this could perhaps be a command for dinitctl; thus it would require the same access level as starting/stopping services and so on.

My main use for this would be able to e.g. smoothly export the dbus session bus address into environment for user services, as well as other session-related variables that are currently not available (because the user-instance of dinit runs separately from the login so that it can properly persist when you say, log in on another tty and then log out on the first one) so that user services can handle things that rely on these, without needing clunky command wrappers.

My other option is to implement this as a part of dinit-userservd (which is my daemon that manages automatic user instances of dinit) and then provide a special command that will invoke another command through environment managed by dinit-userservd and have user services do something like command = /usr/bin/dinit-run-session another-command ... but I would first like to hear whether you'd consider implementing this into dinit itself (or accept contribution of such functionality) as it would make for nicer service files, and make the functionality available to system services as well (though this could actually be an anti-feature, not quite sure yet)

[Feature request] status of service

I would like to see status and small log of specific service using
dinitctl status service-name
Using dinitctl list does show status , but it fill up whole screen.

CI: Provide "fuzz" for dinit!

Goal

Provide "fuzz" step for dinit in CI

ToDo

  • Checkout dinit fuzzer backend (For debugging,improve...) (#91)
  • Learn more about Fuzzer & LLVM's libfuzzer
  • Provide "fuzz" ci workflow(s) (#96)

References

https://en.wikipedia.org/wiki/Fuzzing: Fuzzing, From Wikipedia, the free encyclopedia:

In programming and software development, fuzzing or fuzz testing is an automated software testing technique that involves providing invalid, unexpected, or random data as inputs to a computer program. The program is then monitored for exceptions such as crashes, failing built-in code assertions, or potential memory leaks. Typically, fuzzers are used to test programs that take structured inputs. This structure is specified, e.g., in a file format or protocol and distinguishes valid from invalid input. An effective fuzzer generates semi-valid inputs that are "valid enough" in that they are not directly rejected by the parser, but do create unexpected behaviors deeper in the program and are "invalid enough" to expose corner cases that have not been properly dealt with.
For the purpose of security, input that crosses a trust boundary is often the most useful.[1] For example, it is more important to fuzz code that handles the upload of a file by any user than it is to fuzz the code that parses a configuration file that is accessible only to a privileged user.

https://github.com/davmac314/dinit/blob/master/BUILD file description:

dinit/BUILD

Lines 116 to 128 in ececd16

In addition to the standard test suite, there is experimental support for fuzzing the control
protocol handling using LLVM/clang's fuzzer (libFuzzer). Change to the `src/tests/cptests`
directory and build the "fuzz" target:
make fuzz
Then create a "corpus" directory and run the fuzzer:
mkdir corpus
./fuzz corpus
This will auto-generate test data as it finds input which triggers new execution paths. Check
libFuzzer documentation for further details.

LLVM's libfuzzer project page:

https://llvm.org/docs/LibFuzzer.html

cf37c78 broke make check

g++ -D_GLIBCXX_USE_CXX11_ABI=1 -std=c++11 -Os -Wall -fno-rtti -fno-plt -flto -fsanitize=address,undefined -MMD -MP -Iincludes -I../../dasynq -c ../../service.cc -o service.o
g++ -fsanitize=address,undefined -o cptests cptests.o ../test-bpsys.o ../test-dinit.o control.o dinit-log.o service.o load-service.o proc-service.o baseproc-service.o run-child-proc.o -flto -Os
make[3]: Leaving directory '/root/dinit/src/tests/cptests'
./tests
test1...                     tests: tests.cc:71: void test1(): Assertion `s2->get_state() == service_state_t::STOPPED' failed.
make[2]: *** [Makefile:12: run-tests] Aborted (core dumped)
make[2]: Leaving directory '/root/dinit/src/tests'
make[1]: *** [Makefile:54: check] Error 2
make[1]: Leaving directory '/root/dinit/src'
make: *** [Makefile:12: check] Error 2

Commit earlier make check and make check-igr finished with success.

Tweak documentation/comments about `-t`/`--service` in `dinit.cc`

It needs to be revised:

dinit/src/dinit.cc

Lines 375 to 396 in a5a5e43

// If we are running as init (PID=1), the Linux kernel gives us all command line arguments it was
// given but didn't recognize, and, uh, *some* that it did recognize, which means we can't assume
// that anything is a service name (for example "nopti" seems to get passed through to init).
// However, we can look for special names that we know aren't kernel parameters, such as "single".
//
// (Note this may have been fixed in recent kernels: see changelog for 5.15.46/5.18.3,
// "x86: Fix return value of __setup handlers")
//
// LILO puts "auto" on the command line for unattended boots, but we don't care about that and want
// it filtered.
//
// We don't expect to see options beginning with '-' appear on the kernel command line either, so we
// can interpret those as dinit arguments. In particular if we see -m or -o, we assume that every
// name we see from then is a service name (i.e. process_sys_args is set false when we seem them,
// see above).
//
// (Note, you can give "--" on the kernel command line to pass every option from that point to init
// directly, but init doesn't see the "--" itself, which makes it less useful, since we still can't
// tell whether a "name" was intended as a kernel parameter or init parameter).
// So, long story short: if we think we're PID 1 and we haven't seen -m or -c options yet, only
// recognise "single" as a service name and ignore everything else.

Related: #69 & #76

Test fails after commit 18acacf

make check fails after "base_process_service: properly clean up in destructor" commit

$ make check
make -C src check
make[1]: Entering directory '/home/marcin.skarbek/projects/dinit/src'
make -C tests check
make[2]: Entering directory '/home/marcin.skarbek/projects/dinit/src/tests'
mkdir -p includes
rm -rf includes/*.h
cd includes; ln -sf ../../includes/*.h .
cd includes; ln -sf ../test-includes/*.h .
g++ -D_GLIBCXX_USE_CXX11_ABI=1 -std=c++11 -Os -Wall -fno-rtti -fno-plt -flto -fsanitize=address,undefined -MMD -MP -Iincludes -I../dasynq -c ../proc-service.cc -o proc-service.o
In file included from ../proc-service.cc:8:0:
includes/proc-service.h: In destructor ‘virtual base_process_service::~base_process_service()’:
includes/proc-service.h:141:28: error: ‘class service_child_watcher’ has no member named ‘unreserve’; did you mean ‘add_reserved’?
             child_listener.unreserve(event_loop);
                            ^~~~~~~~~
                            add_reserved
includes/proc-service.h:143:23: error: ‘class process_restart_timer’ has no member named ‘deregister’
         restart_timer.deregister(event_loop);
                       ^~~~~~~~~~
make[2]: *** [Makefile:29: proc-service.o] Error 1
make[2]: Leaving directory '/home/marcin.skarbek/projects/dinit/src/tests'
make[1]: *** [Makefile:27: check] Error 2
make[1]: Leaving directory '/home/marcin.skarbek/projects/dinit/src'
make: *** [Makefile:7: check] Error 2```

serverless dinitctl

In a installation dinit has never been launched yet, so I cant enable important services like networkmanager, ssh... (I dont remember this problem before, is this a new change?)

I'd like to dinitctl to enable/disable services without dinit server, or at least enable... if I execute the command as root. Always or with a option ? or maybe a workaround ?
Thanks.

[Feature Request] populate $SERVICE_NAME or logdir configuration

It would be helpful to make $SERVICE_NAME or similar expand to the service name on service load (if sub-vars is set).
This could eliminate the need to retype the logfile name for each service.

alternatively it could also be quite nice to have a logdir option (or handle dirs in logfiles) by creating a logfile <service name>.log in that directory.

If that is already a thing then I did not find it yet.

dinitctl: `dinitctl status` shows `Process ID:` for scripted services!

Hi.
I created a service as follows:

type = scripted
command = /etc/init.d/resolvconf start
stop-command = /etc/init.d/resolvconf stop
logfile = /var/log/resolvconf.log

depends-on = networking
waits-for = dnscrypt-proxy

Then I saw its status via dinitctl status resolvconf command:

Service: resolvconf
    State: STARTED
    Activation: explicitly started
    Process ID: 0

But dinitctl try to show Process ID for scripted services!
This appears to be a regression as this was not an issue in the past.

regards

dinitctl socket unreachable

Hi,

It seems like the socket at /dev/dinitctl becomes unavailable as we are mounting /dev to tmpfs.
I haven't had a deep look at the code, but I assume it should re-open a file descriptor after /dev has been mounted (instead of during / rw remount) in order for it to work.

# dinitctl -s list
dinitctl: connect: No such file or directory

# netstat -lna
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node Path
unix  2      [ ACC ]     SEQPACKET  LISTENING       7040 /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING       8594 /dev/dinitctl
unix  3      [ ]         DGRAM                      8602 
unix  3      [ ]         DGRAM                      8601 

# lsof 1
1       /sbin/dinit     /dev/console
1       /sbin/dinit     /dev/console
1       /sbin/dinit     /dev/console
1       /sbin/dinit     anon_inode:[eventpoll]
1       /sbin/dinit     anon_inode:[timerfd]
1       /sbin/dinit     anon_inode:[timerfd]
1       /sbin/dinit     anon_inode:[signalfd]
1       /sbin/dinit     socket:[8594]
1       /sbin/dinit     /etc/dinit.d/boot.d

/dev/dinitctl is not present.
I'm using eudev.

[Feature request] Environment variables in command

Did you considered handling variables in service command?
Use case: running confd service inside docker container with ETCD_HOST variable provided by docker and dinit as PID 1.

type = process
command = /usr/bin/confd -interval 5 -node ${ETCD_HOST}
options = runs-on-console

Currently that has to be handled by sh script that is wrapping confd command.

Ability to restart a service

Hi,

I don't think there's a way to restart a service short of stopping and starting it?

It'd be neat to have dinitctl restart <service>.

[Feature Request] Silent boot

Something like systemd and s6 (s6-linux-init) do when the quiet argument is passed through cmdline (e.g, using grub).

How to Activiate dinit socket at recovery mode?

Hello. I was working on a recovery service when I ran into a problem (I do not know if it is a bug or not?)
dinit loads recovery service when boot fails but dinit does not create /run/dinitctl socket! This will make dinitctl unavailable. This makes it harder to restore the system in recovery mode.
But unlike recovery mode, in single-user mode, dinit creates the /run/dinitctl socket correctly.
How can this problem be solved? I had several solutions in mind, none of which worked better than fixing it in dinit.

regards

Suggestions about comparison with InitNG

dinit/doc/COMPARISON

Lines 287 to 294 in 716fc4d

InitNG (http://initng.org/trac; defunct)
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
A highly modular init system which apparently offers dependency management
(as Dinit does). Portability status is unclear; may be Linux-only (Dinit
strives for portability). Development may have ceased (website is now showing
Japanese text which I am unable to read) although there are what looks like
maintenance commits from 2017 in the Github repository at
https://github.com/initng/initng.

  • development ceased in February 2013.
  • focused on Linux but portable, there used to be a port for Haiku.
  • Website is dead.
  • offers dependencies.

container example?

I read your blog post, and was intrigued, i've been looking for a lightweight systemd replacement for containers, focusing on simple service management, without going back to sysvinit with shell scripts.

I tried using it as a general purpose service manager, to allow child containers to just copy in a /etc/dinit.d/boot, and let dinit just take over... but i'm getting "free(): invalid pointer" whenever trying to use /sbin/dinit as the container's PID 1.

Any suggestions? I'm trying 0.8.0

Package in Fedora/EPEL repos

I would like to finally publish my package in the main Fedora repo and then add it to EPEL. For that, I would like to have recently added -o in a released version. So what's the plan for the next release?

[RFE] Individual environment config files

It would be nice to be able to create a file with environment variables for each service. Even better when that file could be created by another service (as a dependency) and loaded during the execution of a particular service.

`make fuzz` target is broken!

Hello.
I was working on the fuzzer when I ran into several problems:

  1. includes addresses is broken:

    fuzz: fuzz.cc $(fuzz_parent_test_objects) $(fuzz_objects)
    clang++ -std=c++11 -g -O1 -Iincludes -I../../dasynq -fsanitize=fuzzer,address,undefined,leak fuzz.cc $(fuzz_parent_test_objects) $(fuzz_objects) -o fuzz
    $(fuzz_parent_test_objects): fuzz-%.o: ../%.cc
    clang -O1 -fsanitize=address,undefined,fuzzer-no-link,leak -MMD -MP -I../includes -I../../dasynq -c $< -o $@
    $(fuzz_objects): fuzz-%.o: ../../%.cc
    clang -O1 -fsanitize=address,undefined,fuzzer-no-link,leak -MMD -MP -Iincludes -I../../dasynq -c $< -o $@

    (fixed by #92).

  2. prepare-incdir target not runned by make when building fuzz target! its target prepare include dirs for building tests/fuzz (fixed by #94)

  3. because fuzz target not runned by upstream MakeFile, mconfig.h not exist but we need mconfig.h for buliding fuzz target (fixed by #95):

❯ make fuzz
clang -O1 -fsanitize=address,undefined,fuzzer-no-link,leak -MMD -MP -Iincludes -I../../../dasynq/include -c ../test-bpsys.cc -o fuzz-test-bpsys.o
clang -O1 -fsanitize=address,undefined,fuzzer-no-link,leak -MMD -MP -Iincludes -I../../../dasynq/include -c ../test-dinit.cc -o fuzz-test-dinit.o
clang -O1 -fsanitize=address,undefined,fuzzer-no-link,leak -MMD -MP -Iincludes -I../../../dasynq/include -c ../../control.cc -o fuzz-control.o
In file included from ../../control.cc:6:
In file included from includes/control.h:16:
In file included from includes/service-listener.h:4:
includes/service-constants.h:4:10: fatal error: 'mconfig.h' file not found
#include "mconfig.h"
         ^~~~~~~~~~~
1 error generated.

regards

external readiness notification mechanism

I wonder if it would be worthwhile to implement another mechanism for readiness notification of services. Currently we can do that from the service itself using a file descriptor passed either directly or through an environment variable. This is a simple and fairly flexible mechanism, but it cannot be applied universally.

I was thinking of possibly introducing a new mechanism that would utilize some kind of ready-command field. I'm thinking the system could simply do:

  1. If present, issue the command alongside the service's command
  2. Wait for the ready-command to exit
  3. If the exit status of it was 0, service is considered ready
  4. In case of a non-zero exit status, bring down the service

This could be adapted to lots of things that do not directly support any kind of readiness notification. In my particular case I would use this for the dbus activation support I am working on (the command would take care of waiting for the service to appear on the bus).

WDYT?

Integration tests will crash on version 0.15.0 or later!

Hello.
I researched the strange breakdown of integration tests and came to an important conclusion!
I found that these bugs only exist in 0.15.0 or 0.15.1 and 0.14.0 has no problem with that!
"Why did I come to this conclusion?"
1- When integration tests in github actions are turned on, they are broken!
2- I tested this issue on drone.mobintestserver.ir. 0.14.0 has no problem with make check-igr. But 0.15.1 fails in make check-igr‍.
0.14.0: https://drone.mobintestserver.ir/Dinit_on_Devuan/dinit/42/1/2
0.15.1: https://drone.mobintestserver.ir/Dinit_on_Devuan/dinit/45

But there is a strange thing:
make check-igr on my computer does not fail with any of the dinit versions!

Really weird problem!

[Feature Request] Enable stop-command for process and bgprocess

Rationale

Certain services, such as ejabberd, prosody (for process) and mailman (for bgprocess), require a stop command to cleanly finish before the process is terminated.

While using scripted is also possible, I want to know whether we can supervise these processes or it's a lost cause for these kind of services.

[Feature Request] check-command for scripted services

Right now, scripted services cannot be supervised, however in some scenarios there might be a way to supervise them via command line arguments (for example, for a service that listens on a port, we could check if the port is still open). Having a check-command field in the service description files could therefore be useful for that kind of purpose.
I imagine the command outputting a non-zero exit value if the process is not running (stopped or starting) and zero if the service is running.
Additionally, a check-command-interval could prove useful so that Dinit can poll the status every X seconds and restart a service if needed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.