fiss 0.3.3 turn the lights on GitHub ================================================================================ Aloha! You somehow landed on the website of fiss (Friedel's Initialization and Service Supervision). fiss is a supervision suite for Unix and Unix-like systems with the power off system initialization. This project is based on runit and other daemontools-based utilities. fiss' manuals --------------------------------------------------------------------------------
* chpst(8) - runs a program with a changed process state
* finit(8) - a UNIX process no 1
* fsvc(8) - fiss' service controller
* fsvs(8) - fiss' service superviser
* halt(8) - halts the system
* reboot(8) - reboots the system
* poweroff(8) - stop the system
* modules-load(8) - configure kernel modules at boot
* shutdown(8) – bring down the system
* sigremap(8) - catches signals and redirects mapped signal to executable
* vlogger(8) - log messages to syslog or an arbitrary executable
* zzz(8) - suspend or hibernate your system
What does an init-system do? -------------------------------------------------------------------------------- After the kernel has loaded all the hardware stuff and setting up a working environment, it executes /sbin/init by default which mounts pseude-drives, the root-drive read-writable and more. This depends on your system, the package does include start and stop scripts and basic agetty services. After the initialization is done, services must be started. A service is a long- running process, which needs to be restarted if it suddenly terminates. FreeBSD and other BSD's as far as I know, are handling services pretty rudimentally with plain shell scripts and without supervision. The most Linux distributions are shipped with SystemD which is the opposite of FreeBSD's rc.d idea. SystemD is one massive and bulky project with a lot of (useless) features. I've used Void Linux which is shipped with runit, a daemontools-derivate with initialization. Unlike SystemD, runit is a fine in-between: minimal but feature-rich. Bit too minimal so I thought of making fiss! Why fiss tho? -------------------------------------------------------------------------------- fiss is a lightweight and easy-to-use tool for initializing and supervising long-running services on Unix-like systems. It provides a simple and reliable way to start, stop, and monitor services. It supports automatic restarts, logging, and customizable startup options. It's no fork and uses the standard POSIX libc without other runtime dependencies. fiss support all the features to make services efficient running. It can be compatible with runit and daemontools utilities and is highly customizable at runtime to make fiss fit your needs. fiss vs runit -------------------------------------------------------------------------------- runit is a good init-system and is lovely to use but there are some features which are just missing.
* fiss has service-ordering (aka. dependencies), thus if service-b depends on service-a, you can configure it as a dependency and fiss will keep service-a running as long as service-b is running.
* fiss has background-services, some services just won't let you run them in foreground. runit solves this problem with pause, a little program which just waits on an incoming signal. But this solution requires extra resources and a process-slot. It's bearly possible to hit the process-roof but for every process, the kernel needs to reserve memory and manage cpu-time.
* runit has no built-in environment settings, it always runs services with a clear environment and you can modify it with chpst. That extends the process chain and cost more start-up time. fiss has build-in environment options for changing the user and group, the arguments, argv[0] or environment-variables. This project also includes a simplified and rewritten version of chpst, for compatibility use.
* runit's controller sv is really basic. It does not need to be very beautiful or feature-rich, but enabling services and enabling services once (one time after boot) is not possible. runit's down-file method seems more like a hack. fiss supports enabling and once-enabling by default. If you like sv's simplicity or its helpers like vsv or rsv, there is a compatibility-layer for runit or daemontools
* finit and fsvc directly call the service executable. That means there is no process-chaining as runit does. If you are running runit as init (runit-init): - kernel executes runit-init - this executes runit - runit forks and executes /etc/runit/{1,2,3} - /etc/runit/2 executes runsvdir - runsvdir forks and executes runsv - and finally runsv executes the underlying service executable
* Every fork and execute causes an overhead. Also runsvdir is decentralized, thus no central control unit can be used and every runsv has its own control unit.
* On the other hand this results in more security, if a executable failes due to a bug, the underlying executable will catch this (if implemented). Which implementation is better is up to yourself.
* fiss and runit are entirely written in C, init has to be minimal and a garbage collector would only slow down the whole system. With C you have direct control of the operating system.
* fiss is written from scratch using the libc implementaions, this results in a readable code thus easier for contributers to dive into the codebase. runit and daemontools are written using the djb-library which is an alternative general library. It's completely fine to use the library and maybe it is even faster than your libc-implementation (glibc, musl, freebsd-libc).
Installation -------------------------------------------------------------------------------- Now that you are really hyped to install fiss, you first have to compile it. To compile make sure you have installed the dependencies. - C compiler like gcc or clang which supports the gnu99-standard - POSIX-compliant shell like dash or bash - GNU make - md2man to make the manuals If running fiss, you require to have following dependencies installed: - POSIX-compliant shell like dash or bash - GNU awk Download the last release from GitHub or clone this project with git to build from HEAD. +------------------------------------------------------------------------------+ | git clone https://github.com/friedelschoen/fiss.git | | cd fiss/ | +------------------------------------------------------------------------------+ Then you have to compile the project with make. +------------------------------------------------------------------------------+ | make binary # to compile the executables | | make manual # to compile the manuals | +------------------------------------------------------------------------------+ Executables are now stored in ./bin, standard configuration-files are stored in ./etc, runtime-required files are in ./share and manuals in ./man. Installation on Void Linux -------------------------------------------------------------------------------- If you don't have the source-tree yet, clone and bootstrap it with git. +------------------------------------------------------------------------------+ | git clone https://github.com/void-linux/void-packages.git | | cd void-packages/ | | ./xbps-src binary-bootstrap | +------------------------------------------------------------------------------+ fiss is not a official package yet, as it's too unstable to include, but you can add my void-packages as remote and compile. +------------------------------------------------------------------------------+ | git remote add fiss https://github.com/friedelschoen/void-packages.git | | git pull fiss fiss | | ./xbps-src pkg fiss | | xi fiss # if xtools is installed | | sudo xbps-install -R hostdir/binpkgs fiss # if xtools is not installed | +------------------------------------------------------------------------------+ Convert runit services -------------------------------------------------------------------------------- The very most runit-service should work with fsvc but some not very efficient, thats why converting them is handy. Because runit (and fiss) only execute the ./run script, these scripts can be pretty bulky. All services installed by xbps, thus available in void-packages follow some unwritten rules (unwritten as I haven't found them yet but services tent to follow some similarities). Services tent to follow this structure: +------------------------------------------------------------------------------+ | #!/bin/sh (1) | | | | [ -r ./conf ] && . .conf (2) | | exec chpst -u user:group service -p $PORT $OPTS (3) | +------------------------------------------------------------------------------+ (1) The ./run-file always is a shell-executable, which executes the actual service. (2) If ./conf exist in the service-directory, it is sourced. (3) chpst is executed with some parameters like -u which executes as user. chpst then executes service with modified state and predefined parameters from ./conf. This is a foreground service, it means that the executable does not exit til the service is stopped. If the executable exits, you can expect the service to be down. fiss also includes a stripped-down version of chpst for compability use, fiss includes a basic state management. You can extract the chpst-part to ./user and ./env (see below). If you executable has static parameters, thus no ./conf and no environment-variables, you can also pass the parameters in ./params and sym-link the executable directly to ./run. Void Linux packages always comes with a symbolic link ./supervise to /run/runit/supervise.<service>, which is meant for read-only systems running runit (expecting /run/ to be a temporary filesystem). If you are running a writable system, you can remove the link and fiss will create a directory. If you are running a read-only system you can either create the directory /run/runit/ and don't have to mess with runit-services or at an other location and sym-link the supervise-directories by yourself. If your ./run execute looks like the following, stressing the pause... +------------------------------------------------------------------------------+ | #!/bin/sh | | | | service -p 990 start | | exec chpst -b service pause | +------------------------------------------------------------------------------+ ... and you ./finish like that... +------------------------------------------------------------------------------+ | #!/bin/sh | | | | service stop | +------------------------------------------------------------------------------+ ... it's a runit-background service which should be converted to a fiss-service. The service executable exits immediately, the actual service is running in the background. pause is a runit-hack, a program which just suspends until it is signaled by runit. It blocks a process-slot and the kernel still needs to care about it. fiss handles background-services different by calling ./start and ./stop. You can safely remove the last exec line and rename ./run to ./start and ./finish to ./stop and it should work. Getting Started -------------------------------------------------------------------------------- fiss does not parse any configuration file, everything is configured through different files inside for example /etc/service.d. Following files are executed by finit:
* /usr/share/fiss/start This is the entry point of your system (similar to /etc/runit/1). By default this script sources files in unix-order inside /etc/start.d/*.sh.
* /etc/service.d/* In this directory the services are stored, underneath is descripted how a service is constructed. The utility fsvs is written to supervise a service- directory without issuing start and stop mechanisms.
* /usr/share/fiss/stop This is the ending point of your system-lifetime (similar to /etc/runit/3). By default this script sources file in unix-order inside /etc/stop.d/*.sh.
zzz is a utility shipped with fiss to suspend your system, following files are executed by zzz.
* /usr/share/fiss/suspend This file is executed before suspending, by default this script sources files in unix-order inside /etc/zzz.d/suspend/*.sh.
* /usr/share/fiss/resume This file is executed after suspending (thus before resuming), by default this script sources files in unix-order inside /etc/zzz.d/resume/*.sh.
How to create a service? -------------------------------------------------------------------------------- Services are usually placed into /etc/service.d, a services is a long-running executable like for example sshd, which should be running the whole lifetime of your system. Sadly do some services terminate before your system halts because of an error or signaling, this is where fiss plays its role.
* ./run Usually your service runs in the foreground, in this case you can create a run executable, either linked to the actual binary or as a script that executes the service. run is meant to be running the whole time in the foreground and must not daemonize itself into the background as fiss would restart it. +----------------------------------------------------------------------------+ | #!/bin/sh | | | | [ -r ./conf ] && . ./conf | | | | exec myservice $ARGS | +----------------------------------------------------------------------------+This example sources conf in the service-directory if present and executes myservice with $ARGS.
* ./start If your services cannot be run in the foreground, you should execute link it to start, start is a short-running executable, if start exits it is considered as running. To supervise your services, it's handy to provide a pid-file inside your service as some services provide print its process-id to the console. If no pid-file is found you must implement a stop file. +----------------------------------------------------------------------------+ | #!/bin/sh | | | | myserver --print-pid > ./pid | +----------------------------------------------------------------------------+
* ./pid This is a plain-text file containing just the PID of the service in decimal.
* ./stop This script is meant to stop the service, if this file exits the service is considered inactive. This file must not coexist with pid. +----------------------------------------------------------------------------+ | #!/bin/sh | | | | myserver2 --stop | +----------------------------------------------------------------------------+
* ./depends This file contains newline-demilitered service-names which are dependencies of the service. dependencies are started before the service will be started and stopped if no enabled and no other service depend on it. Dependencies are just started, no consideration will be done that the dependency is actually active.
* +----------------------------------------------------------------------------+ | dbus | | networking | +----------------------------------------------------------------------------+
* ./setup If this file is present and executable, it will be executed before run or start, it is meant for example to create files or directories. +----------------------------------------------------------------------------+ | #!/bin/sh | | | | mkdir /var/myserver | +----------------------------------------------------------------------------+
* ./finish If this file is present and executable, it will be executed after run has exited or after stop was executed. This is meant to remove unnessasary files or directories.
* +----------------------------------------------------------------------------+ | #!/bin/sh | | | | rm -rf /var/myserver | +----------------------------------------------------------------------------+
* ./log If this file is present, fiss will write the stdout and stderr of run to it. This will be done without any modifications.
* ./log/ service If this directory is present and a valid service-directory, stdout and stderr of your service will be redirected to the run of the log-service. This is done with a internal pipe, thus no data will be lost of either services failes.
* ./no-log If this file is present, no logging will be done at all. This is meant for very verbose services, which would overflout the system. If log, log/ or no-log is not present, the output of will be redirected to /run/fiss/log/<service>.
* ./up-<runlevel> If this file is present, the services will be started automatically and restarted if this services dies. On other systems, this is called 'enabling' a service.
* ./once-<runlevel> If this file is present, the services will be started automatically but not restarted if this services dies.
To be a valid service, run, start or depends must be present. If only depends is present, this service is a dummy service thus no actual action will be taken but starting and stopping dependencies. start, stop, setup and finish are executed as the same user as fsvs or finit is started, thus root in the most cased. user, env, params are not read when handling a background-service. Every file will be executed in the services directory, reading a file like './conf' will be read out of the service directory.