Skip to contentSkip to conversation

common init infrastructure

RFC Superseded Alex Suykov 3 participants 25 messages Mar 21, 2015 – Mar 24, 2015

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover common init infrastructure

This series is intended to clean up buildroot init system somewhat, removing the need for extensive sysv and systemd handling code in every package that installs init bits, and allowing alternative init systems to be implemented with reasonable amount of effort.

Overview of the changes:

* drop per-package sysv and systemd files, introduce common format used to generate files for both of them, use a script to do the conversion from common format to sysv or systemd.

* remove sysv and systemd installation code from package .mk files, let pkg-generic handle it.

* remove sysv-specific files from skeleton, and sysv-specific hacks from system/system.mk. Use a dedicated script to write inittab, handling global conditionals (root rw/ro, serial getty and so on)

* remove user definitions from package .mk files, and mkdirs from per-package sysv initscript, use per-package .users and .files instead in a way similar to .hash files.

Expected benefits:

* (almost) all packages get both sysv and systemd files at the same time and without the need to support them separately.

* init-related changes can be introduced without patching all 70+ individual packages that install startup files.

* new init systems can be introduced with only minor effort, including lightweight ones with controlled (foreground) daemons.

This series includes the infrastructure changes, and a couple of package patches to show how it looks like. Complete set of package patches uploaded here: https://github.com/arsv/br/

This series is for reviewing, not for merging.

Signature · 1 line
2.0.3
#1 lore raw

RFC 1/11 common service startup files

This patch introduces support infrastructure for per-project .run files.

Any .run files in package directory are picked up by pkg-generic code, fed to support/init/install-run script which converts them into either sysv initscripts or systemd unit files and installs those into predefined locations. The package itself provides only the .run files, no code in package .mk file is necessary.

Packages that install some of their services conditionally may set $(PKG)_INIT = list of run files to install. As a side effect, this removes the need to handle S99foo S99bar vs foo.service bar.service with the package .mk file.

Packages that need to substititue some values within their service files may set $(PKG)_INIT = KEY:value KEY:value ..., which will be handled by install-run. The substitutions will be applied to sysv and systemd files.

In case particular init system needs hand-crafted startup files or cannot handle certain services at all, install-run may be told so using special lines in the .run file.

This patch does not remove existing BR2_INIT_{SYSV,SYSTEMD} hooks. Each package should either provide .run files or define hooks, but not both.

---
 package/Makefile.in          |  10 +
 package/pkg-generic.mk       |  23 +++
 support/init/install-run     | 457 +++++++++++++++++++++++++++++++++++++++++++
 support/init/install-tmpconf |   7 +
 4 files changed, 497 insertions(+)
 create mode 100755 support/init/install-run
 create mode 100755 support/init/install-tmpconf
package/Makefile.in +10 -0
index 803b162..599fe7f 100644
@@ -408,6 +408,16 @@ ifeq ($(BR2_COMPILER_PARANOID_UNSAFE_PATH),y)
 export BR_COMPILER_PARANOID_UNSAFE_PATH=enabled
 endif
 
+ifdef BR2_INIT_SYSV
+BR2_INIT = initscripts
+else ifdef BR2_INIT_BUSYBOX
+BR2_INIT = initscripts
+else ifdef BR2_INIT_SYSTEMD
+BR2_INIT = systemd
+else
+BR2_INIT = none
+endif
+
 include package/pkg-download.mk
 include package/pkg-autotools.mk
 include package/pkg-cmake.mk
package/pkg-generic.mk +23 -0
index c1b379b..fe7de8a 100644
@@ -762,10 +762,33 @@ ifneq ($$(call suitable-extractor,$$($(2)_SOURCE)),$$(XZCAT))
 DL_TOOLS_DEPENDENCIES += $$(firstword $$(call suitable-extractor,$$($(2)_SOURCE)))
 endif
 
+# Init, users and files are for target image only
+ifeq ($4,target)
+
+$(2)_INIT ?= $$(notdir $$(wildcard package/$1/*.run))
+$(2)_POST_INSTALL_TARGET_HOOKS += $(2)_INSTALL_INIT
+
+# This will expand to (nothing) if none of the files are present
+# in the package directory.
+ifndef $(2)_INSTALL_INIT
+define $(2)_INSTALL_INIT
+	$$(call ifargs,support/init/install-run $$(BR2_INIT) \
+		$$($$(PKG)_INIT_SUBST),$$(addprefix package/$1/,$$($$(PKG)_INIT)))
+	$$(call ifargs,support/init/install-tmpconf $$(BR2_INIT),$$(wildcard package/$1/*.tmp.conf))
+endef
+endif
+
+endif # $4 == target
+
 endif # $(2)_KCONFIG_VAR
 endef # inner-generic-package
 
 ################################################################################
+define ifargs
+	$(if $2,$1 $2)
+endef
+
+################################################################################
 # generic-package -- the target generator macro for generic packages
 ################################################################################
 
support/init/install-run new file +457 -0

457 lines not on this page · raw message

support/init/install-tmpconf new file +7 -0
new file mode 100755
index 0000000..080dcd7
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+test "$1" = 'systemd' && shift || exit
+mkdir -p output/target/etc/tmpfiles.d/
+for i in "$@"; do
+	cp $i output/target/etc/tmpfiles.d/${i/.tmp.conf/.conf}
+done
Signature · 1 line
2.0.3
#2 lore raw

RFC 1/11 common service startup files

Quoted 8 lines · Alex Suykov

This patch introduces support infrastructure for per-project .run files.

Any .run files in package directory are picked up by pkg-generic code, fed to support/init/install-run script which converts them into either sysv initscripts or systemd unit files and installs those into predefined locations. The package itself provides only the .run files, no code in package .mk file is necessary.

Quoted 6 lines

Packages that install some of their services conditionally may set $(PKG)_INIT = list of run files to install. As a side effect, this removes the need to handle S99foo S99bar vs foo.service bar.service with the package .mk file.

Packages that need to substititue some values within their service

substitute

Quoted 3 lines

files may set $(PKG)_INIT = KEY:value KEY:value ..., which will be handled by install-run. The substitutions will be applied to sysv and systemd files.

I don't see why this is needed, and it probably makes the install-run script
more complicated.

Quoted 6 lines

In case particular init system needs hand-crafted startup files or cannot handle certain services at all, install-run may be told so using special lines in the .run file.

This patch does not remove existing BR2_INIT_{SYSV,SYSTEMD} hooks.

Good!

Quoted 2 lines

Each package should either provide .run files or define hooks, but not both.
---

Missing SoB, but perhaps that's intentional because it's not ready for inclusion?

Quoted 15 lines
 package/Makefile.in          |  10 +
 package/pkg-generic.mk       |  23 +++
 support/init/install-run     | 457 +++++++++++++++++++++++++++++++++++++++++++
 support/init/install-tmpconf |   7 +
 4 files changed, 497 insertions(+)
 create mode 100755 support/init/install-run
 create mode 100755 support/init/install-tmpconf
package/Makefile.in +0 -0
index 803b162..599fe7f 100644
@@ -408,6 +408,16 @@ ifeq ($(BR2_COMPILER_PARANOID_UNSAFE_PATH),y)
 export BR_COMPILER_PARANOID_UNSAFE_PATH=enabled
 endif

package/Makefile.in ifeq ($(BR2_COMPILER_PARANOID_UNSAFE_PATH),y) · line 419

Quoted 10 lines
package/Makefile.in +9 -0
 
+ifdef BR2_INIT_SYSV
+BR2_INIT = initscripts
+else ifdef BR2_INIT_BUSYBOX
+BR2_INIT = initscripts
+else ifdef BR2_INIT_SYSTEMD
+BR2_INIT = systemd
+else
+BR2_INIT = none
+endif

It's nicer to do this kind of switch in system/Config.in:

config BR2_INIT

	string
	default "initscripts" if BR2_INIT_SYSV || BR2_INIT_BUSYBOX
	default "systemd" if BR2_INIT_SYSTEMD
	default "none"
Quoted 9 lines
package/Makefile.in +1 -0
+
 include package/pkg-download.mk
 include package/pkg-autotools.mk
 include package/pkg-cmake.mk
package/pkg-generic.mk +0 -0
index c1b379b..fe7de8a 100644

package/pkg-generic.mk ifneq ($$(call suitable-extractor,$$($(2)_SOURCE)),$$(XZCAT)) · line 768

Quoted 7 lines
package/pkg-generic.mk +4 -0
@@ -762,10 +762,33 @@ ifneq ($$(call suitable-extractor,$$($(2)_SOURCE)),$$(XZCAT))
 DL_TOOLS_DEPENDENCIES += $$(firstword $$(call suitable-extractor,$$($(2)_SOURCE)))
 endif
 
+# Init, users and files are for target image only
+ifeq ($4,target)
+
+$(2)_INIT ?= $$(notdir $$(wildcard package/$1/*.run))

package/$1/ is not correct, because it could be outside of the package
directory (e.g. external) or in a subdirectory. Use $(pkgdir) instead (note:
only one $!).

package/pkg-generic.mk ifneq ($$(call suitable-extractor,$$($(2)_SOURCE)),$$(XZCAT)) · line 773

Quoted 5 lines
package/pkg-generic.mk +5 -0
+$(2)_POST_INSTALL_TARGET_HOOKS += $(2)_INSTALL_INIT
+
+# This will expand to (nothing) if none of the files are present
+# in the package directory.
+ifndef $(2)_INSTALL_INIT

There should never be any reason for a package to override _INSTALL_INIT, they
can just avoid adding *.run files or setting _INIT.

Therefore, I'd also move this to the %/.stamp_target_installed rule. That makes
it easier to understand because of less $$. Note that that is also the place where the current init handling is done. With that done, there is also no need to keep the definition of _INIT in the ifeq($4,target) condition.

package/pkg-generic.mk ifneq ($$(call suitable-extractor,$$($(2)_SOURCE)),$$(XZCAT)) · line 776

Quoted 3 lines
package/pkg-generic.mk +3 -0
+define $(2)_INSTALL_INIT
+	$$(call ifargs,support/init/install-run $$(BR2_INIT) \
+		$$($$(PKG)_INIT_SUBST),$$(addprefix package/$1/,$$($$(PKG)_INIT)))

The line is split at an inconvenient place here.

I wouldn't do this $(notdir) and $(addprefix) magic. It's OK for the package
.mk file to be required to provide the full path to the .run file.

package/pkg-generic.mk ifneq ($$(call suitable-extractor,$$($(2)_SOURCE)),$$(XZCAT)) · line 777

Quoted 1 line
package/pkg-generic.mk +1 -0
+	$$(call ifargs,support/init/install-tmpconf $$(BR2_INIT),$$(wildcard package/$1/*.tmp.conf))

This tmpdir support should probably be in a separate patch.

BTW, shouldn't tmpdirs be handled for sysv as well? Typically, the init script
will create the tmpdir...

package/pkg-generic.mk ifneq ($$(call suitable-extractor,$$($(2)_SOURCE)),$$(XZCAT)) · line 789

Quoted 12 lines
package/pkg-generic.mk +8 -0
+endef
+endif
+
+endif # $4 == target
+
 endif # $(2)_KCONFIG_VAR
 endef # inner-generic-package
 
 ################################################################################
+define ifargs
+	$(if $2,$1 $2)
+endef

This should go to pkg-utils instead.

support/init/install-run

Quoted 10 lines
package/pkg-generic.mk +2 -0
+
+################################################################################
 # generic-package -- the target generator macro for generic packages
 ################################################################################
 
support/init/install-run new file +0 -0
new file mode 100755
index 0000000..24b79c7

I've spent about an hour trying to understand this script, and I'm still not
fully there... So this probably falls in the "too complicated" category. I still have a bunch of stylistic remarks below, but here are some overall thoughts.

- The script should do something as simple as possible. The variable
substitution is an example of something that is (probably) adding complexity, and it can be done in a different way, e.g. running a sed script afterwards.

- The script should only handle cases that are actually used. So start with
something extremely simple that covers a few interesting cases, and leave the others to use the old initscripts system.

- There should be a lot more comments to explain what is done and why.

- You should start with the documentation of what it's supposed to do. That
makes it easier for us to understand what it's doing (and to say which things it shouldn't do :-)

- Avoid the getattr() etc. magic. It's easier to understand what's going on if
things are in a simple and explicit dict.

- Use existing infrastructure where possible. For instance, you could change
the .run format into .ini format and use configparser, or you could use the shlex module for parsing.

- Don't make names too short, they should always be descriptive. 'w' is not a
good name for a function. If typing is a problem for you, get an editor that supports completion.

- You should take care of the exit conditions (and document them). If there is
something wrong with a .run file or with the script itself, it should exit fatally and the build should be stopped. But if the .run file contains something that is not supported for this init system, this should be non-fatal.

Quoted 8 lines
support/init/install-run new file +7 -0
@@ -0,0 +1,457 @@
+#!/usr/bin/env python
+
+# Usage:
+#
+#   install-init [-] init-system [VAR1:val1 VAR2:val2 ...] file1.run file2.run ...
+#
+# init-system is one the values from inits array below.

support/init/install-run line 17

Quoted 10 lines
support/init/install-run new file +10 -0
+#
+# The script will write relevant configuration files to output/target/etc/...,
+# so it should be called from the top Buildroot directory.
+# Use - to write all files to the current directory (useful for debugging)
+
+# Bundling all init systems into a single script, vs having install-init-(system)
+# scripts for each system, may look strange, but it turns out most of the code
+# below is common for all init systems.
+
+from sys import stderr, argv

We don't do that. Just

import sys

... sys.argv ...

support/init/install-run line 27

Quoted 10 lines
support/init/install-run new file +10 -0
+from re import match, sub
+from os.path import dirname, basename
+from os import makedirs, fdopen, fstat, fchmod
+from os import O_RDONLY, O_WRONLY, O_CREAT, O_TRUNC
+from os import open as osopen
+from os import read as osread
+from os import write as oswrite
+
+inits = ['initscripts', 'systemd']
+output = None

Don't put this in a global variable. A member of Run would be a good place.

support/init/install-run line 33

Quoted 6 lines
support/init/install-run new file +6 -0
+nopath = False
+
+class Run:
+    def __init__(self, name, path):
+        self.path = path    # full .run file name, for error reporting
+        self.name = name    # service name = stem(basename(path))

This splitting into path and name should be handled here, in the constructor,
and not in the caller.

support/init/install-run line 43

Quoted 10 lines
support/init/install-run new file +10 -0
+
+        # This is a bit more complicated than it should be
+        # to allow reporting incorrect global keys while still
+        # accepting unadorned commands for pre/post groups.
+
+        for k in ['description', 'user', 'group', 'umask',
+                  'pidfile', 'priority',
+                  'after', 'requires', 'wantedby',
+                  'busname', 'conflicts', 'killwith', 'restart']:
+            setattr(self, k, None)

This will also be simpler if you just use a dict.

Quoted 22 lines
support/init/install-run new file +22 -0
+
+        # sequence:
+        #   pre-exec-post
+        #   pre-start-stop-post
+        #   pre  (for run-once scripts)
+        self.pre = []
+        self.post = []
+        self.acts = ['exec', 'start', 'stop', 'reload']
+        for k in self.acts:
+            setattr(self, k, None)
+
+        for k in inits:
+            setattr(self, k, None)
+
+        # variable substitutions
+        # (default values from .run until update() is called)
+        self.subs = {}
+
+    def has(self, key):
+        return hasattr(self, key)
+
+    def get(self, key):

support/init/install-run line 75

Quoted 10 lines
support/init/install-run new file +10 -0
+        return getattr(self, key)
+
+    def set(self, key, val):
+        setattr(self, key, val)
+
+    def update(self, values):
+        self.subs.update(values)
+
+    def isempty(self):
+        return (not self.exec and not self.start and not self.pre and not self.post)

exec is a reserved word in python2.

Quoted 23 lines
support/init/install-run new file +23 -0
+
+    def substcmds(self):
+        for k in ['pre', 'post']:
+            attr = getattr(self, k)
+            for i, s in enumerate(attr):
+                attr[i] = self.substvars(s)
+        for k in ['exec', 'start', 'stop', 'reload']:
+            attr = getattr(self, k)
+            if not attr is None:
+                setattr(self, k, self.substvars(attr))
+
+    def substvars(self, value):
+        def var(m):
+            k = m.group(1)
+            if k in self.subs:
+                return self.subs[k]
+            else:
+                return m.group(0)
+
+        ret = sub(r'\$([A-Za-z]+)', var, value)
+        return ret
+
+

support/init/install-run line 108

Quoted 10 lines
support/init/install-run new file +10 -0
+def die(message, *args):
+    stderr.write((message+"\n") % tuple(args))
+    exit(-1)
+
+
+def openread(filename):
+    try:
+        fh = open(filename)
+    except OSError:
+        die("Can't open %s" % filename)

This wrapper doesn't make a lot of sense. Such failures should anyway not
occur, because the script is always called with .run files. So it's OK to dump an exception stack on the user.

Quoted 5 lines
support/init/install-run new file +5 -0
+    return fh
+
+def parse(name, path):
+    run = Run(name, path)
+    fh = openread(path)

support/init/install-run line 123

Quoted 10 lines
support/init/install-run new file +10 -0
+    inscript = False    # after the first empty line
+    pastpre = False     # after exec/start/stop
+    firstline = True
+
+    for line in fh:
+        line = line.strip()
+
+        # Use ## for description, but only if it is the first line
+        if firstline and match('^## ', line):
+            run.description = line[3:]

Why this ## hack? "description = This is program foo" is much more descriptive.

Quoted 39 lines
support/init/install-run new file +39 -0
+        else:
+            firstline = False
+
+        # Skip comments in non-command section, but pass them through
+        # when inscript
+        if not inscript and match(r'^#', line):
+            continue
+
+        # Empty line marks the start of script section
+        if not inscript and match(r'^\s*$', line):
+            inscript = True
+            continue
+
+        m = match(r'^[A-Z_0-9]+=(.*)', line)
+        if m and not inscript:
+            run.subs[m.group(1)] = m.group(2)
+            continue
+
+        m = match(r'^([A-Za-z]+)(\s+(.*))?', line)
+        if m:
+            key, val = m.group(1), m.group(3)
+        else:
+            key, val = None, None
+
+        if not inscript and not key:
+            die("%s: bad line", path)
+
+        if (not inscript and key) or (inscript and key in run.acts):
+            if run.get(key):
+                die("%s: cannot re-assign %s", path, key)
+            elif run.has(key):
+                run.set(key, val if m.group(2) else True)
+            else:
+                die("%s: unknown key %s", path, key)
+            if key in run.acts:
+                pastpre = True
+        elif inscript:
+            if pastpre:
+                run.post.append(line)

support/init/install-run line 172

Quoted 10 lines
support/init/install-run new file +10 -0
+            else:
+                run.pre.append(line)
+
+    if not run.priority:
+        if run.exec:
+            run.priority = '50'
+        elif run.start:
+            run.priority = '40'
+        else:
+            run.priority = '10'

The reasoning behind these static priorities should be explained somewhere.

Quoted 7 lines
support/init/install-run new file +7 -0
+
+    return run
+
+def openwrite(path, mode):
+    global nopath
+
+    if nopath:

support/init/install-run line 189

Quoted 10 lines
support/init/install-run new file +10 -0
+        path = basename(path)
+    else:
+        try:
+            makedirs(dirname(path))
+        except OSError:
+            pass
+
+    fd = osopen(path, O_WRONLY | O_CREAT | O_TRUNC)
+    fchmod(fd, mode)
+    return fd

This whole umask thing is useless IMHO. You also don't provide an example for it.

If someone is so paranoid that they think an init script should be
non-readable, they should give it a BR2_ROOTFS_DEVICE_TABLE entry.

And anyway, use chmod instead of fchmod.

So, if the umask is gone, you can just do open(path, 'w')

support/init/install-run line 199

Quoted 10 lines
support/init/install-run new file +10 -0
+
+def writeto(path, mode):
+    global output
+    fd = openwrite(path, mode)
+    output = fdopen(fd, 'w')
+
+# write
+def w(fmt, *subst):
+    global output
+    output.write((fmt+"\n") % subst)

Making a function for this is really not worth it.

Quoted 7 lines
support/init/install-run new file +7 -0
+
+# write newline
+def wnl(): w("")
+
+# write lines
+def wl(fmt, array):
+    for l in array:

support/init/install-run line 216

Quoted 10 lines
support/init/install-run new file +10 -0
+        w(fmt, l)
+
+# write-tab, write-tab-tab
+def wt(fmt, *subst): w("\t" + fmt, *subst)
+def wtt(fmt, *subst): w("\t\t" + fmt, *subst)
+
+# ------------------------------------------------------------------------------
+
+# return either cmd or su cmd; the caller naturally handles shell commands
+def maybesu(r, cmd):

Should be a method of Run.

support/init/install-run line 225

Quoted 9 lines
support/init/install-run new file +9 -0
+    if r.user:
+        return "su - %s -c '%s'" % (r.user, cmd)
+    else:
+        return cmd
+
+# ------------------------------------------------------------------------------
+
+def initscripts(r):
+    writeto('output/target/etc/init.d/S%02d%s' % (int(r.priority), r.name), 0o755)

Ah yes here you need to set the exec bit of course.

output/ is wrong, it could be modified by O=. Instead, you should pass
TARGET_DIR in the environment or on the commandline and use that.

Quoted 37 lines
support/init/install-run new file +37 -0
+
+    (start, stop) = initscripts_ssd(r)
+
+    w("#!/bin/sh\n")
+    if r.description:
+        w("# %s\n", r.description)
+
+    for k, v in r.subs.items():
+        w("%s=%s", k, v)
+    if r.subs:
+        wnl()
+
+    if r.umask:
+        w("umask %s", r.umask)
+
+    w("case \"$1\" in")
+    w(" start)")
+    for c in r.pre:
+        wtt("%s", maybesu(r, c))
+    if r.start:
+        wtt("%s", maybesu(r.start))
+    elif start:
+        wtt("%s", start)
+    elif not r.pre and not r.post:
+        die("%s: cannot write initscript without any commands to run", r.path)
+    wtt(";;")
+
+    wt("stop)")
+    if r.stop and not r.stop is True:
+        wtt("%s", r.stop)
+    elif r.start or r.exec:
+        wtt("%s", stop)
+    for c in r.post:
+        wtt("%s", maybesu(c))
+    wtt(";;")
+
+    if r.reload:

support/init/install-run line 272

Quoted 10 lines
support/init/install-run new file +10 -0
+        wt("reload)")
+        wtt("%s", r.reload)
+        wtt(";;")
+
+    wt("restart)")
+    wtt("$0 stop")
+    wtt("$0 start")
+    wtt(";;")
+
+    w("esac")

A multiline template with %-formatting would be easier to understand. So:

completestart = map(maybesu,r.start).join('\n\t\t') completestart += ...
completestop = ...

output.write("""
#! /bin/sh
%s

case "$1" in

	start)
		%s;;
	stop)
		%s;;
	restart|reload)
		$0 stop
		$0 start
		;;

esac
""" % (substitions, completestart, completestop)

Quoted 4 lines
support/init/install-run new file +4 -0
+
+# generate start-stop-daemon commands from r.exec
+# run -> (start, stop)
+def initscripts_ssd(r):

support/init/install-run line 286

Quoted 10 lines
support/init/install-run new file +10 -0
+    if not r.exec:
+        return None, None
+
+    if r.pidfile:
+        pidfile = r.pidfile
+    else:
+        pidfile = '/var/run/%s.pid' % r.name
+
+    ssdopts = ['-S']
+    sskopts = ['-K']

ssdopts and sskopts are visually too similar to make it easy to distinguish.
What about startopts and stopopts?

Quoted 4 lines
support/init/install-run new file +4 -0
+    if r.user:
+        ssdopts.append('-c')
+        ssdopts.append(r.user)
+    if r.group:

support/init/install-run line 300

Quoted 10 lines
support/init/install-run new file +10 -0
+        ssdopts.append('-g')
+        ssdopts.append(r.group)
+    if not r.pidfile and not r.start:
+        ssdopts.append('-m')
+    if pidfile:
+        ssdopts.append('-p')
+        ssdopts.append(pidfile)
+        sskopts.append('-p')
+        sskopts.append(pidfile)
+    ssdopts = (" ".join(ssdopts))

It's ugly if a variable is first a list and then a string. But you don't need
to do it here, just do the join below where it's used to construct start/stop.

support/init/install-run line 304

Quoted 4 lines
support/init/install-run new file +4 -0
+    sskopts = (" ".join(sskopts))
+
+    cmd = sub(r'\s.*', '', r.exec)
+    arg = sub(r'^\S+', ' --', r.exec) if cmd != r.exec else ''

cmd = re.sub(r'\s.*', ' -- ', 1)

	start = "start-stop-daemon %s -b %s" % (" ".join(ssdopts), cmd)

support/init/install-run line 307

Quoted 3 lines
support/init/install-run new file +3 -0
+
+    start = "start-stop-daemon %s -b %s%s" % (ssdopts, cmd, arg)
+    stop = "start-stop-daemon %s" % sskopts

I prefer an explicit /sbin/start-stop-daemon - when manually starting/stopping,
/sbin is not always in the path.

Quoted 4 lines
support/init/install-run new file +4 -0
+
+    return (start, stop)
+
+# ------------------------------------------------------------------------------

support/init/install-run line 321

Quoted 10 lines
support/init/install-run new file +10 -0
+
+def systemd(r):
+    writeto("output/target/usr/lib/systemd/system/%s.service" % r.name, 0o644)
+    r.substcmds()
+
+    if r.after:
+        after = r.after
+    elif r.priority and r.priority >= '90':
+        after = "syslog.service network.service"
+    elif r.priority and r.priority >= '50':

If that is the meaning of the priorities, perhaps it's better to give them
names rather than numbers.

Quoted 50 lines
support/init/install-run new file +50 -0
+        after = "syslog.service"
+    else:
+        after = None
+
+    w("[Unit]")
+    if r.description:
+        w("Description=%s", r.description)
+    if after:
+        w("After=%s", after)
+    if r.requires:
+        w("Requires=%s", r.requires)
+    if r.conflicts:
+        w("Conflicts=%s", r.conflicts)
+    wnl()
+
+    w("[Service]")
+    if r.user:
+        w("User=%s", r.user)
+    if r.group:
+        w("Group=%s", r.group)
+    if r.pidfile and not r.exec:
+        w("PIDFile=%s", r.pidfile)
+    if r.start or r.exec:
+        for c in r.pre:
+            w("ExecStartPre=%s", c)
+
+    if r.exec:
+        w("ExecStart=%s", r.exec)
+    elif r.start:
+        w("Type=forking")
+        w("ExecStart=%s", r.start)
+    elif r.pre:
+        w("Type=oneshot")
+        wl("ExecStart=%s", r.pre)
+
+    if r.stop and not r.exec:
+        w("ExecStop=%s", r.stop)
+
+    for c in r.post:
+        w("ExecStartPost=%s", c)
+    if r.reload:
+        w("ExecReload=%s", r.reload)
+    if r.restart:
+        w("Restart=%s", r.restart)
+    elif r.exec:
+        w("Restart=always")
+    wnl()
+
+    w("[Install]")
+    if r.wantedby:

support/init/install-run line 381

Quoted 10 lines
support/init/install-run new file +10 -0
+        w("WantedBy=%s", r.wantedby)
+    else:
+        w("WantedBy=multi-user.target")
+
+# ------------------------------------------------------------------------------
+
+# Usage:
+#     bypass systemd foo.service
+#     bypass initscripts foo.init foo.line
+#     bypass inittab -

This bypass syntax is hard to understand IMHO. Can you find something
simpler/clearer and more verbose? If you would switch to ini format, it could be something like

[initscripts]
cp = package/foo/S10start

     /etc/init.d/S10start

[systemd]
cp-ln = package/foo/foo.service
/usr/lib/systemd/system/foo.service /etc/systemd/system/multi-user.target.wants

Quoted 20 lines
support/init/install-run new file +20 -0
+
+bypasstable = {
+    'initscripts': [
+        ('*:*.init',    'output/target/etc/init.d/S$1$2'),
+        ('*.init',      'output/target/etc/init.d/S50$1'),
+        ('*.conf',      'output/target/etc/config.d/*'),
+        ('S*',          'output/target/etc/init.d/*') ],
+    'systemd': [
+        ('*.service',   'output/target/usr/lib/systemd/system/*.service'),
+        ('*.tmp.conf',  'output/target/usr/lib/tmpfiles.d/*.conf') ]
+}
+
+def bypass(run, init, arg):
+    if arg == '-': return
+    rules = bypasstable[init]
+    for f in arg.split():
+        copied = False
+        for r in rules:
+            m = match(r[0].replace('*','(.*)'), basename(f))
+            if not m: continue

support/init/install-run line 411

Quoted 10 lines
support/init/install-run new file +10 -0
+            copyfile(sub(r'.*:', '', f),
+                    r[1].replace('*', m.group(1))
+                        .replace('$1', m.group(1))
+                        .replace('$2', m.group(2)))
+            copied = True
+            break
+        if not copied:
+            die('no destination for %s', f)
+
+def copyfile(src, dst):

Use shutil.copyfile instead of inventing your own.

Quoted 52 lines
support/init/install-run new file +46 -0
+    f = osopen(src, O_RDONLY)
+    s = fstat(f)
+    o = openwrite(dst, s.st_mode)
+    buf = osread(f, s.st_size)
+    oswrite(o, buf)
+
+# ------------------------------------------------------------------------------
+
+if len(argv) > 1 and argv[1] == '-':
+    nopath = True
+    del argv[1]
+
+if len(argv) < 2:
+    die("Usage: install-init [-] init-system file.run file.run ...")
+
+init = argv[1]
+
+if not init:
+    die("Bad call")
+
+if init in inits:
+    writer = globals()[init]
+else:
+    die("Unknown init system %s", init)
+
+subst = []
+files = []
+
+for a in argv[2:]:
+    eq = a.find(':')
+    if eq >= 0:
+        subst.append((a[0:eq], a[eq+1:]))
+    elif a.endswith('.run'):
+        files.append((basename(a)[:-4], a))
+    else:
+        die("Bad argument: %s", a)
+
+for f in files:
+    run = parse(f[0], f[1])
+    run.update(subst)
+    if getattr(run, init):
+        bypass(run, init, getattr(run, init))
+    if r.isempty():
+        continue
+    else:
+        writer(run)
support/init/install-tmpconf new file +0 -0
new file mode 100755
index 0000000..080dcd7

support/init/install-tmpconf line 7

Quoted 7 lines
support/init/install-tmpconf new file +7 -0
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+test "$1" = 'systemd' && shift || exit
+mkdir -p output/target/etc/tmpfiles.d/
+for i in "$@"; do
+	cp $i output/target/etc/tmpfiles.d/${i/.tmp.conf/.conf}
+done

You also didn't give an example of this, but I have the feeling it would make
more sense to put this in the .run script as well. For sysv, the tmpfile should be created in the init script; for systemd, it's done by tmpfiles.

Regards,
Arnout

Quoted 1 line
Signature · 6 lines
Arnout Vandecappelle                          arnout at mind be
Senior Embedded Software Architect            +32-16-286500
Essensium/Mind                                http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium           BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F
#3 lore raw

RFC 1/11 common service startup files

Sun, Mar 22, 2015 at 12:57:50AM +0100, Arnout Vandecappelle wrote:

Thanks for extensive review, a lot of good points which I skip in this reply because they should go directly into the code.

Quoted 1 line

Missing SoB, but perhaps that's intentional because it's not ready for inclusion?

Well, partially, and partially I just forgot -s when re-splitting commits.

Quoted 7 lines
Quoted 3 lines

files may set $(PKG)_INIT = KEY:value KEY:value ..., which will be handled by install-run. The substitutions will be applied to sysv and systemd files.

I don't see why this is needed, and it probably makes the install-run script
more complicated.

BR2_PACKAGE_GPSD_DEVICES, and keeping it a variable in the resulting initscript. Or maybe in /etc/default.
If sed substitutiions are ok, this can be done much simplier of course:

sed s!DEVICES!/dev/ttyS1! package/gpsd/gpsd.run > build/gpsd-.../gpsd.run support/init/install-run build/gpsd-.../gpsd.run

Quoted 2 lines

BTW, shouldn't tmpdirs be handled for sysv as well? Typically, the init script will create the tmpdir...

I saw this as systemd-specific.
Looking at the packages, yes, makes sense to have some kind of generic tmpdir variable.

Quoted 3 lines

- The script should only handle cases that are actually used. So start with
something extremely simple that covers a few interesting cases, and leave the others to use the old initscripts system.

Why I was trying handle as many packages as possible: I'm pretty sure something like 80% of them will work immediately with only the basic support, but it would be really bad to find a show-stopper among the remaining 20%. Something that would require changing the way the whole thing works.

Perhaps it's ok to drop bad cases for now, leave them as initscripts-only and expect the users do something about the unsupported cases themselves.

Quoted 3 lines

- Use existing infrastructure where possible. For instance, you could change
the .run format into .ini format and use configparser, or you could use the shlex module for parsing.

Regarding ini files, I was thinking about using a kind of extended/simplified .service format. Systemd being systemd, it would cover all cases, and it's got some documentation already.

The problem is that there are pretty long shell scripts that do not fit well within .ini files. Examples: sunxi-mali, ti-gfx, am33-cm3 and maybe some others. That's why I tried to keep .run files looking somewhat like shell scripts.

Well, that and I don't like systemd documentation all that much.

Quoted 4 lines

This bypass syntax is hard to understand IMHO. Can you find something simpler/clearer and more verbose? If you would switch to ini format, it could be something like

Quoted 8 lines

[initscripts]
cp = package/foo/S10start

     /etc/init.d/S10start

[systemd]
cp-ln = package/foo/foo.service
/usr/lib/systemd/system/foo.service /etc/systemd/system/multi-user.target.wants

The primary goal of the whole changeset is to separate package-specific and init-system-specific things, moving the latter out of packages, so that a change in systemd directory layout (for instance) would not require patching all the packages.

This is why I try to specify startup ordering (priority 10 or multi-user.target in this case) indirectly, and why I try to avoid explicit paths.
I see this as a part of init config format, not a part of service configuration.

The package does not need to know where to put those and how to name them. All it needs is to have its process started, at some point.

#4 lore raw

RFC 1/11 common service startup files

Quoted 10 lines · Alex Suykov
Quoted 3 lines
Quoted 3 lines

- The script should only handle cases that are actually used. So start with
something extremely simple that covers a few interesting cases, and leave the others to use the old initscripts system.

Why I was trying handle as many packages as possible: I'm pretty sure something like 80% of them will work immediately with only the basic support, but it would be really bad to find a show-stopper among the remaining 20%. Something that would require changing the way the whole thing works.

Perhaps it's ok to drop bad cases for now, leave them as initscripts-only and expect the users do something about the unsupported cases themselves.

I think it's important that there is always a fallback with custom stuff. And
for me, it's perfectly OK if the infrastructure handles only 50% of the cases and the other 50% have to be custom.

Regards,
Arnout

Signature · 6 lines
Arnout Vandecappelle                          arnout at mind be
Senior Embedded Software Architect            +32-16-286500
Essensium/Mind                                http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium           BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F
#5 lore raw

RFC 1/11 common service startup files

In reply to Alex Suykov
Quoted 3 lines · Alex Suykov

The problem is that there are pretty long shell scripts that do not fit well within .ini files. Examples: sunxi-mali, ti-gfx, am33-cm3 and maybe some others. That's why I tried to keep .run files looking somewhat like shell scripts.

Why would it not fit in an ini file? You just have to add some indentation:

startscript =
echo 1 > /sys/devices/...
bla bla bla
and we're done

Regards,
Arnout

Signature · 6 lines
Arnout Vandecappelle                          arnout at mind be
Senior Embedded Software Architect            +32-16-286500
Essensium/Mind                                http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium           BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F
#6 lore raw

RFC 1/11 common service startup files

In reply to Alex Suykov

Alex, All,

On 2015-03-21 20:27 +0200, Alex Suykov spake thusly:

Quoted 8 lines

This patch introduces support infrastructure for per-project .run files.

Any .run files in package directory are picked up by pkg-generic code, fed to support/init/install-run script which converts them into either sysv initscripts or systemd unit files and installs those into predefined locations. The package itself provides only the .run files, no code in package .mk file is necessary.

Quoted 4 lines

Packages that install some of their services conditionally may set $(PKG)_INIT = list of run files to install. As a side effect, this removes the need to handle S99foo S99bar vs foo.service bar.service with the package .mk file.

I think this shoule be always set in the .mk, even if not conditional, and that pkg-generic only handles what's been explicitly declared by the package.

Quoted 4 lines

Packages that need to substititue some values within their service files may set $(PKG)_INIT = KEY:value KEY:value ..., which will be handled by install-run. The substitutions will be applied to sysv and systemd files.

What we previously discussed was something like the following (for sysv-init):

/etc/init.d/S??foo <- startup script for package 'foo'

/etc/defaults/foo <- contains default configuration of package
'foo', as installed by Buildroot.

/etc/config/foo <- optional file, contains the user-supplied
override configuration for package 'foo'

Then, the "startup script" would read those files, starting with the one in /etc/defaults/ and then, if present, the one in /etc/config/ . This would allow /etc to be read-only, and /etc/config to be a read-write mountpoint.

Those files would be provided by the packages, like is done for now.

And similarly for systemd, except a lot of packages are now providing systemd unit files, and there is no reason we would provide our own instead, since that would probably bit-rot in the long term, so we probably would prefer to use whatever upstream provides.

So, what we really care about are sysv initscripts, since they are in a very bad shape:
- upstream-provided scripts are too ugly, and often tied to a

    particular distro;

- our own scripts are mot very clean either, for some have been around for a looong time.

Quoted 3 lines

In case particular init system needs hand-crafted startup files or cannot handle certain services at all, install-run may be told so using special lines in the .run file.

I'm afraid this would be abused in the long run, becasue .run syntax is too specific to Buildroot.

Quoted 2 lines

This patch does not remove existing BR2_INIT_{SYSV,SYSTEMD} hooks. Each package should either provide .run files or define hooks, but not both.

Right.

Regards,
Yann E. MORIN.

Signature · 6 lines
.-----------------.--------------------.------------------.--------------------.
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
| +33 223 225 172 `------------.-------:  X  AGAINST      |  \e/  There is no  |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |
'------------------------------^-------^------------------^--------------------'
#7 lore raw

RFC 1/11 common service startup files

Quoted 11 lines · Yann E. MORIN

Alex, All,

On 2015-03-21 20:27 +0200, Alex Suykov spake thusly:

Quoted 8 lines

This patch introduces support infrastructure for per-project .run files.

Any .run files in package directory are picked up by pkg-generic code, fed to support/init/install-run script which converts them into either sysv initscripts or systemd unit files and installs those into predefined locations. The package itself provides only the .run files, no code in package .mk file is necessary.

Quoted 8 lines
Quoted 4 lines

Packages that install some of their services conditionally may set $(PKG)_INIT = list of run files to install. As a side effect, this removes the need to handle S99foo S99bar vs foo.service bar.service with the package .mk file.

I think this shoule be always set in the .mk, even if not conditional, and that pkg-generic only handles what's been explicitly declared by the package.

Well, that's not how we do it for .hash and .patch...

I would rather remove the option of setting _INIT from the package.mk file, if
the goal is to simplify things.

Quoted 7 lines
Quoted 4 lines

Packages that need to substititue some values within their service files may set $(PKG)_INIT = KEY:value KEY:value ..., which will be handled by install-run. The substitutions will be applied to sysv and systemd files.

What we previously discussed was something like the following (for sysv-init):

We discussed it but I didn't agree :-)

I want to keep things simple, and any customisation should go through fs-overlay.

Quoted 6 lines

/etc/init.d/S??foo <- startup script for package 'foo'

/etc/defaults/foo <- contains default configuration of package
'foo', as installed by Buildroot.

Quoted 7 lines

/etc/config/foo <- optional file, contains the user-supplied
override configuration for package 'foo'

Then, the "startup script" would read those files, starting with the one in /etc/defaults/ and then, if present, the one in /etc/config/ . This would allow /etc to be read-only, and /etc/config to be a read-write mountpoint.

Sounds nice, but you'd still need something like uci to manage /etc/config, and
then it probably wouldn't even work with uci...

Quoted 7 lines

Those files would be provided by the packages, like is done for now.

And similarly for systemd, except a lot of packages are now providing systemd unit files, and there is no reason we would provide our own instead, since that would probably bit-rot in the long term, so we probably would prefer to use whatever upstream provides.

I totally agree with this: if a package provides a systemd unit file, it should
be used and we shouldn't touch it.

However, I believe that a package will normally just install the unit file and
not add the symlink to actually start it, so that's something we still have to take care of.

Quoted 7 lines

So, what we really care about are sysv initscripts, since they are in a very bad shape:
- upstream-provided scripts are too ugly, and often tied to a

    particular distro;

- our own scripts are mot very clean either, for some have been around for a looong time.

Agreed.

Quoted 7 lines
Quoted 4 lines

In case particular init system needs hand-crafted startup files or cannot handle certain services at all, install-run may be told so using special lines in the .run file.

I'm afraid this would be abused in the long run, becasue .run syntax is too specific to Buildroot.

I'm not sure what you mean with abuse. For downstream packages, we don't really
care if they're using custom scripts or .run, and for patches to buildroot we'll make sure that they use .run if possible.

Regards,
Arnout

Quoted 9 lines
Quoted 3 lines

This patch does not remove existing BR2_INIT_{SYSV,SYSTEMD} hooks. Each package should either provide .run files or define hooks, but not both.

Right.

Regards,
Yann E. MORIN.

Signature · 6 lines
Arnout Vandecappelle                          arnout at mind be
Senior Embedded Software Architect            +32-16-286500
Essensium/Mind                                http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium           BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F
#8 lore raw

RFC 2/11 per-package .users and .files lists

In reply to Alex Suykov

Following .run and .hash files, move package-specific users and file permissions from .mk strings into standalone files, to be picked up by pkg-generic code.
No additional code in package .mk is necessary.

This change does not simplify things much at present, but it removes inter-package dependency via make variables. Without this patch, reading all enabled package/*/*.mk files from a single Makefile was necessary to build user and permission lists. With this patch, the data is stored outside of make, possibly allowing one make invocation per package .mk file in the future.

To keep installed per-package .users and .files, a new directory is introduced: output/parts.
The directory is meant for stuff that is installed during build stage but does not belong in the target/ directory, at least not without some processing.

---
 Makefile                   |  1 +
 fs/common.mk               | 21 +++++++++++++--------
 package/pkg-generic.mk     |  2 ++
 support/init/install-parts |  5 +++++
 4 files changed, 21 insertions(+), 8 deletions(-)
 create mode 100755 support/init/install-parts
Makefile +1 -0
index 33a89b1..98f67d3 100644
@@ -156,6 +156,7 @@ endif
 BR_GRAPH_OUT := $(or $(BR2_GRAPH_OUT),pdf)
 
 BUILD_DIR := $(BASE_DIR)/build
+PARTS_DIR := $(BASE_DIR)/parts
 BINARIES_DIR := $(BASE_DIR)/images
 TARGET_DIR := $(BASE_DIR)/target
 # initial definition so that 'make clean' works for most users, even without
fs/common.mk +13 -8
index 5d07f00..e60c82f 100644
@@ -28,12 +28,14 @@
 # BR2_TARGET_ROOTFS_$(FSTYPE)_LZMA exist and are enabled, then the
 # macro will automatically generate a compressed filesystem image.
 
-FAKEROOT_SCRIPT = $(BUILD_DIR)/_fakeroot.fs
-FULL_DEVICE_TABLE = $(BUILD_DIR)/_device_table.txt
+FAKEROOT_SCRIPT = $(PARTS_DIR)/fakeroot.fs
+FULL_DEVICE_TABLE = $(PARTS_DIR)/device_table.txt
 ROOTFS_DEVICE_TABLES = $(call qstrip,$(BR2_ROOTFS_DEVICE_TABLE) \
 	$(BR2_ROOTFS_STATIC_DEVICE_TABLE))
-USERS_TABLE = $(BUILD_DIR)/_users_table.txt
+USERS_TABLE = $(PARTS_DIR)/users_table.txt
 ROOTFS_USERS_TABLES = $(call qstrip,$(BR2_ROOTFS_USERS_TABLES))
+PARTS_LIST_USERS = $(wildcard $(PARTS_DIR)/users/*.users)
+PARTS_LIST_FILES = $(wildcard $(PARTS_DIR)/files/*.files)
 
 # Since this function will be called from within an $(eval ...)
 # all variable references except the arguments must be $$-quoted.
@@ -41,7 +43,7 @@ define ROOTFS_TARGET_INTERNAL
 
 # extra deps
 ROOTFS_$(2)_DEPENDENCIES += host-fakeroot host-makedevs \
-	$$(if $$(PACKAGES_USERS),host-mkpasswd)
+	$$(if $$(PARTS_LIST_USERS),host-mkpasswd)
 
 ifeq ($$(BR2_TARGET_ROOTFS_$(2)_GZIP),y)
 ROOTFS_$(2)_COMPRESS_EXT = .gz
@@ -77,16 +79,19 @@ $$(BINARIES_DIR)/rootfs.$(1): target-finalize $$(ROOTFS_$(2)_DEPENDENCIES)
 	echo "chown -h -R 0:0 $$(TARGET_DIR)" >> $$(FAKEROOT_SCRIPT)
 ifneq ($$(ROOTFS_DEVICE_TABLES),)
 	cat $$(ROOTFS_DEVICE_TABLES) > $$(FULL_DEVICE_TABLE)
-ifeq ($$(BR2_ROOTFS_DEVICE_CREATION_STATIC),y)
-	printf '$$(subst $$(sep),\n,$$(PACKAGES_DEVICES_TABLE))' >> $$(FULL_DEVICE_TABLE)
+ifdef PARTS_LIST_FILES
+	cat $$(PARTS_LIST_FILES) \
+		$$(if $$(BR2_ROOTFS_DEVICE_CREATION_STATIC),,| grep -v ^/dev) \
+			>> $$(FULL_DEVICE_TABLE)
 endif
-	printf '$$(subst $$(sep),\n,$$(PACKAGES_PERMISSIONS_TABLE))' >> $$(FULL_DEVICE_TABLE)
 	echo "$$(HOST_DIR)/usr/bin/makedevs -d $$(FULL_DEVICE_TABLE) $$(TARGET_DIR)" >> $$(FAKEROOT_SCRIPT)
 endif
 ifneq ($$(ROOTFS_USERS_TABLES),)
 	cat $$(ROOTFS_USERS_TABLES) >> $$(USERS_TABLE)
 endif
-	printf '$$(subst $$(sep),\n,$$(PACKAGES_USERS))' >> $$(USERS_TABLE)
+ifdef PARTS_LIST_USERS
+	cat $$(PARTS_LIST_USERS) >> $$(USERS_TABLE)
+endif
 	PATH=$$(BR_PATH) $$(TOPDIR)/support/scripts/mkusers $$(USERS_TABLE) $$(TARGET_DIR) >> $$(FAKEROOT_SCRIPT)
 	echo "$$(ROOTFS_$(2)_CMD)" >> $$(FAKEROOT_SCRIPT)
 	chmod a+x $$(FAKEROOT_SCRIPT)
package/pkg-generic.mk +2 -0
index fe7de8a..009b116 100644
@@ -774,6 +774,8 @@ ifndef $(2)_INSTALL_INIT
 define $(2)_INSTALL_INIT
 	$$(call ifargs,support/init/install-run $$(BR2_INIT) \
 		$$($$(PKG)_INIT_SUBST),$$(addprefix package/$1/,$$($$(PKG)_INIT)))
+	$$(call ifargs,support/init/install-parts users,$$(wildcard package/$1/*.users))
+	$$(call ifargs,support/init/install-parts files,$$(wildcard package/$1/*.files))
 	$$(call ifargs,support/init/install-tmpconf $$(BR2_INIT),$$(wildcard package/$1/*.tmp.conf))
 endef
 endif
support/init/install-parts new file +5 -0
new file mode 100755
index 0000000..f5305fd
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+part="$1"; shift; test -z "$part" && exit 1
+mkdir -p output/parts/$part/
+cp "$@" output/parts/$part/
Signature · 1 line
2.0.3
#9 lore raw

RFC 2/11 per-package .users and .files lists

Quoted 4 lines · Alex Suykov

This change does not simplify things much at present, but it removes inter-package dependency via make variables. Without this patch, reading all enabled package/*/*.mk files from a single Makefile was necessary to build user and permission lists.

But we're not planning to change that... Running a separate make per package
sounds like a terribly bad idea...

Quoted 2 lines

With this patch, the data is stored outside of make, possibly allowing one make invocation per package .mk file in the future.

So, is there any reason left to move USERS and PERMS to a file?

It has one big disadvantage: it spreads out the package logic over different
files. We currently only have a separate file for the hashes, and that was probably a bad idea to begin with (as witnessed by the many version bumps that forget to update the hash file).

Regards,
Arnout

Signature · 6 lines
Arnout Vandecappelle                          arnout at mind be
Senior Embedded Software Architect            +32-16-286500
Essensium/Mind                                http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium           BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F
#10 lore raw

RFC 2/11 per-package .users and .files lists

Quoted 4 lines · Arnout Vandecappelle
Quoted 2 lines

With this patch, the data is stored outside of make, possibly allowing one make invocation per package .mk file in the future.

So, is there any reason left to move USERS and PERMS to a file?

No, none at present, so I'm dropping this idea completely.

Quoted 4 lines

It has one big disadvantage: it spreads out the package logic over different files. We currently only have a separate file for the hashes, and that was probably a bad idea to begin with (as witnessed by the many version bumps that forget to update the hash file).

Ok, that was for the large part to match current .hash handling. I wonder if it makes sense to move hashes into .mk files then, Arch-style.

#11 lore raw

RFC 3/11 init/finalize script

In reply to Alex Suykov

The patch moves the code that handles non-package parts of init configuration out of packages and out of skeleton, gathering it in a dedicated script.

For sysv init, the script writes /etc/inittab, making filesystems are mounted, udev is handled somehow, syslog is started and network is brought up. For systemd, the script handles target symlinks and aliases.

The idea is that options the configure the system as a whole should be handled outside of individual packages.

So instead of letting eudev to install itself as the udev handler, or maybe letting busybox install mdev, it is decided later and outside of either eudev or busybox.

As a side effect, this patch makes sure sysv-specific files are not installed at all if systemd is chosen for the init.

---
 package/busybox/busybox.mk            |   8 --
 package/busybox/mdev.conf             |  35 ------
 package/eudev/S10udev                 |  50 --------
 package/eudev/eudev.mk                |   4 -
 support/init/finalize                 | 207 ++++++++++++++++++++++++++++++++++
 support/init/init.d/S10mdev           |  21 ++++
 support/init/init.d/S10udev           |  50 ++++++++
 support/init/init.d/rcK               |  26 +++++
 support/init/init.d/rcS               |  26 +++++
 support/init/mdev.conf                |  35 ++++++
 support/init/sysv.fini                |   7 ++
 support/init/sysv.init                |  14 +++
 system/skeleton/etc/init.d/S20urandom |  54 ---------
 system/skeleton/etc/init.d/S40network |  28 -----
 system/skeleton/etc/init.d/rcK        |  27 -----
 system/skeleton/etc/init.d/rcS        |  27 -----
 system/skeleton/etc/inittab           |  35 ------
 system/system.mk                      |  32 +-----
 18 files changed, 390 insertions(+), 296 deletions(-)
 delete mode 100644 package/busybox/mdev.conf
 delete mode 100755 package/eudev/S10udev
 create mode 100755 support/init/finalize
 create mode 100755 support/init/init.d/S10mdev
 create mode 100755 support/init/init.d/S10udev
 create mode 100755 support/init/init.d/rcK
 create mode 100755 support/init/init.d/rcS
 create mode 100644 support/init/mdev.conf
 create mode 100644 support/init/sysv.fini
 create mode 100644 support/init/sysv.init
 delete mode 100755 system/skeleton/etc/init.d/S20urandom
 delete mode 100755 system/skeleton/etc/init.d/S40network
 delete mode 100755 system/skeleton/etc/init.d/rcK
 delete mode 100755 system/skeleton/etc/init.d/rcS
 delete mode 100644 system/skeleton/etc/inittab
package/busybox/busybox.mk +0 -8
index a3ac7e7..90f7293 100644
@@ -56,14 +56,6 @@ endef
 
 # If mdev will be used for device creation enable it and copy S10mdev to /etc/init.d
 ifeq ($(BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_MDEV),y)
-define BUSYBOX_INSTALL_MDEV_SCRIPT
-	$(INSTALL) -D -m 0755 package/busybox/S10mdev \
-		$(TARGET_DIR)/etc/init.d/S10mdev
-endef
-define BUSYBOX_INSTALL_MDEV_CONF
-	$(INSTALL) -D -m 0644 package/busybox/mdev.conf \
-		$(TARGET_DIR)/etc/mdev.conf
-endef
 define BUSYBOX_SET_MDEV
 	$(call KCONFIG_ENABLE_OPT,CONFIG_MDEV,$(BUSYBOX_BUILD_CONFIG))
 	$(call KCONFIG_ENABLE_OPT,CONFIG_FEATURE_MDEV_CONF,$(BUSYBOX_BUILD_CONFIG))
package/busybox/mdev.conf deleted +0 -35
deleted file mode 100644
index 247c0ed..0000000
@@ -1,35 +0,0 @@
-# null may already exist; therefore ownership has to be changed with command
-null		root:root 666 @chmod 666 $MDEV
-zero		root:root 666
-full		root:root 666
-random		root:root 444
-urandom		root:root 444
-hwrandom	root:root 444
-grsec		root:root 660
-
-kmem		root:root 640
-mem		root:root 640
-port		root:root 640
-# console may already exist; therefore ownership has to be changed with command
-console		root:tty 600 @chmod 600 $MDEV
-ptmx		root:tty 666
-pty.*		root:tty 660
-
-# Typical devices
-tty		root:tty 666
-tty[0-9]*	root:tty 660
-vcsa*[0-9]*	root:tty 660
-ttyS[0-9]*	root:root 660
-
-# alsa sound devices
-pcm.*		root:audio 660 =snd/
-control.*	root:audio 660 =snd/
-midi.*		root:audio 660 =snd/
-seq		root:audio 660 =snd/
-timer		root:audio 660 =snd/
-
-# input stuff
-event[0-9]+	root:root 640 =input/
-mice		root:root 640 =input/
-mouse[0-9]	root:root 640 =input/
-ts[0-9]		root:root 600 =input/
package/eudev/S10udev deleted +0 -50

50 lines not on this page · raw message

package/eudev/eudev.mk +0 -4
index f5159a2..dab519e 100644
@@ -40,10 +40,6 @@ else
 EUDEV_CONF_OPTS += --disable-gudev
 endif
 
-define EUDEV_INSTALL_INIT_SYSV
-	$(INSTALL) -m 0755 package/eudev/S10udev $(TARGET_DIR)/etc/init.d/S10udev
-endef
-
 # Required by default rules for input devices
 define EUDEV_USERS
 	- - input -1 * - - - Input device group
support/init/finalize new file +207 -0

207 lines not on this page · raw message

support/init/init.d/S10mdev new file +21 -0
new file mode 100755
index 0000000..d386d42
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Start mdev....
+#
+
+case "$1" in
+  start)
+	echo "Starting mdev..."
+	echo /sbin/mdev >/proc/sys/kernel/hotplug
+	/sbin/mdev -s
+	;;
+  stop)
+	;;
+  restart|reload)
+	;;
+  *)
+	echo "Usage: $0 {start|stop|restart}"
+	exit 1
+esac
+
+exit $?
support/init/init.d/S10udev new file +50 -0

50 lines not on this page · raw message

support/init/init.d/rcK new file +26 -0
new file mode 100755
index 0000000..b1fb8f3
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+
+# Stop all init scripts in /etc/init.d
+# executing them in reversed numerical order.
+#
+for i in $(ls -r /etc/init.d/S??*) ;do
+
+     # Ignore dangling symlinks (if any).
+     [ ! -f "$i" ] && continue
+
+     case "$i" in
+	*.sh)
+	    # Source shell script for speed.
+	    (
+		trap - INT QUIT TSTP
+		set stop
+		. $i
+	    )
+	    ;;
+	*)
+	    # No sh extension, so fork subprocess.
+	    $i stop
+	    ;;
+    esac
+done
support/init/init.d/rcS new file +26 -0
new file mode 100755
index 0000000..bd11d5a
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+
+# Start all init scripts in /etc/init.d
+# executing them in numerical order.
+#
+for i in /etc/init.d/S??* ;do
+
+     # Ignore dangling symlinks (if any).
+     [ ! -f "$i" ] && continue
+
+     case "$i" in
+	*.sh)
+	    # Source shell script for speed.
+	    (
+		trap - INT QUIT TSTP
+		set start
+		. $i
+	    )
+	    ;;
+	*)
+	    # No sh extension, so fork subprocess.
+	    $i start
+	    ;;
+    esac
+done
support/init/mdev.conf new file +35 -0
new file mode 100644
index 0000000..247c0ed
@@ -0,0 +1,35 @@
+# null may already exist; therefore ownership has to be changed with command
+null		root:root 666 @chmod 666 $MDEV
+zero		root:root 666
+full		root:root 666
+random		root:root 444
+urandom		root:root 444
+hwrandom	root:root 444
+grsec		root:root 660
+
+kmem		root:root 640
+mem		root:root 640
+port		root:root 640
+# console may already exist; therefore ownership has to be changed with command
+console		root:tty 600 @chmod 600 $MDEV
+ptmx		root:tty 666
+pty.*		root:tty 660
+
+# Typical devices
+tty		root:tty 666
+tty[0-9]*	root:tty 660
+vcsa*[0-9]*	root:tty 660
+ttyS[0-9]*	root:root 660
+
+# alsa sound devices
+pcm.*		root:audio 660 =snd/
+control.*	root:audio 660 =snd/
+midi.*		root:audio 660 =snd/
+seq		root:audio 660 =snd/
+timer		root:audio 660 =snd/
+
+# input stuff
+event[0-9]+	root:root 640 =input/
+mice		root:root 640 =input/
+mouse[0-9]	root:root 640 =input/
+ts[0-9]		root:root 600 =input/
support/init/sysv.fini new file +7 -0
new file mode 100644
index 0000000..e68f97e
@@ -0,0 +1,7 @@
+# Stuff to do for the 3-finger salute
+null::ctrlaltdel:/sbin/reboot
+
+# Stuff to do before rebooting
+null::shutdown:/sbin/ifdown -a
+null::shutdown:/sbin/swapoff -a
+null::shutdown:/bin/umount -a -r
support/init/sysv.init new file +14 -0
new file mode 100644
index 0000000..b56e3c3
@@ -0,0 +1,14 @@
+# /etc/inittab
+#
+# Copyright (C) 2001 Erik Andersen <[email protected]>
+#
+# Note: BusyBox init doesn't support runlevels.  The runlevels field is
+# completely ignored by BusyBox init. If you want runlevels, use
+# sysvinit.
+#
+# Format for each entry: <id>:<runlevels>:<action>:<process>
+#
+# id        == tty to run on, or empty for /dev/console
+# runlevels == ignored
+# action    == one of sysinit, respawn, askfirst, wait, and once
+# process   == program to run
system/skeleton/etc/init.d/S20urandom deleted +0 -54

54 lines not on this page · raw message

system/skeleton/etc/init.d/S40network deleted +0 -28
deleted file mode 100755
index bfdd491..0000000
@@ -1,28 +0,0 @@
-#!/bin/sh
-#
-# Start the network....
-#
-
-# Debian ifupdown needs the /run/network lock directory
-mkdir -p /run/network
-
-case "$1" in
-  start)
- 	echo "Starting network..."
-	/sbin/ifup -a
-	;;
-  stop)
-	echo -n "Stopping network..."
-	/sbin/ifdown -a
-	;;
-  restart|reload)
-	"$0" stop
-	"$0" start
-	;;
-  *)
-	echo "Usage: $0 {start|stop|restart}"
-	exit 1
-esac
-
-exit $?
-
system/skeleton/etc/init.d/rcK deleted +0 -27
deleted file mode 100755
index 59e9c54..0000000
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-
-# Stop all init scripts in /etc/init.d
-# executing them in reversed numerical order.
-#
-for i in $(ls -r /etc/init.d/S??*) ;do
-
-     # Ignore dangling symlinks (if any).
-     [ ! -f "$i" ] && continue
-
-     case "$i" in
-	*.sh)
-	    # Source shell script for speed.
-	    (
-		trap - INT QUIT TSTP
-		set stop
-		. $i
-	    )
-	    ;;
-	*)
-	    # No sh extension, so fork subprocess.
-	    $i stop
-	    ;;
-    esac
-done
-
system/skeleton/etc/init.d/rcS deleted +0 -27
deleted file mode 100755
index de41153..0000000
@@ -1,27 +0,0 @@
-#!/bin/sh
-
-
-# Start all init scripts in /etc/init.d
-# executing them in numerical order.
-#
-for i in /etc/init.d/S??* ;do
-
-     # Ignore dangling symlinks (if any).
-     [ ! -f "$i" ] && continue
-
-     case "$i" in
-	*.sh)
-	    # Source shell script for speed.
-	    (
-		trap - INT QUIT TSTP
-		set start
-		. $i
-	    )
-	    ;;
-	*)
-	    # No sh extension, so fork subprocess.
-	    $i start
-	    ;;
-    esac
-done
-
system/skeleton/etc/inittab deleted +0 -35
deleted file mode 100644
index b1892c1..0000000
@@ -1,35 +0,0 @@
-# /etc/inittab
-#
-# Copyright (C) 2001 Erik Andersen <[email protected]>
-#
-# Note: BusyBox init doesn't support runlevels.  The runlevels field is
-# completely ignored by BusyBox init. If you want runlevels, use
-# sysvinit.
-#
-# Format for each entry: <id>:<runlevels>:<action>:<process>
-#
-# id        == tty to run on, or empty for /dev/console
-# runlevels == ignored
-# action    == one of sysinit, respawn, askfirst, wait, and once
-# process   == program to run
-
-# Startup the system
-null::sysinit:/bin/mount -t proc proc /proc
-null::sysinit:/bin/mount -o remount,rw /
-null::sysinit:/bin/mkdir -p /dev/pts
-null::sysinit:/bin/mkdir -p /dev/shm
-null::sysinit:/bin/mount -a
-null::sysinit:/bin/hostname -F /etc/hostname
-# now run any rc scripts
-::sysinit:/etc/init.d/rcS
-
-# Put a getty on the serial port
-#ttyS0::respawn:/sbin/getty -L ttyS0 115200 vt100 # GENERIC_SERIAL
-
-# Stuff to do for the 3-finger salute
-::ctrlaltdel:/sbin/reboot
-
-# Stuff to do before rebooting
-::shutdown:/etc/init.d/rcK
-::shutdown:/sbin/swapoff -a
-::shutdown:/bin/umount -a -r
system/system.mk +4 -28
index 4a1eb4a..c5ce1d3 100644
@@ -87,35 +87,11 @@ endef
 endif
 TARGET_FINALIZE_HOOKS += SYSTEM_BIN_SH
 
-ifeq ($(BR2_TARGET_GENERIC_GETTY),y)
-ifeq ($(BR2_PACKAGE_SYSVINIT),y)
-# In sysvinit inittab, the "id" must not be longer than 4 bytes, so we
-# skip the "tty" part and keep only the remaining.
-define SYSTEM_GETTY
-	$(SED) '/# GENERIC_SERIAL$$/s~^.*#~$(shell echo $(TARGET_GENERIC_GETTY_PORT) | tail -c+4)::respawn:/sbin/getty -L $(TARGET_GENERIC_GETTY_OPTIONS) $(TARGET_GENERIC_GETTY_PORT) $(TARGET_GENERIC_GETTY_BAUDRATE) $(TARGET_GENERIC_GETTY_TERM) #~' \
-		$(TARGET_DIR)/etc/inittab
-endef
-else
-# Add getty to busybox inittab
-define SYSTEM_GETTY
-	$(SED) '/# GENERIC_SERIAL$$/s~^.*#~$(TARGET_GENERIC_GETTY_PORT)::respawn:/sbin/getty -L $(TARGET_GENERIC_GETTY_OPTIONS) $(TARGET_GENERIC_GETTY_PORT) $(TARGET_GENERIC_GETTY_BAUDRATE) $(TARGET_GENERIC_GETTY_TERM) #~' \
-		$(TARGET_DIR)/etc/inittab
-endef
-endif
-TARGET_FINALIZE_HOOKS += SYSTEM_GETTY
-endif
-
-ifeq ($(BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW),y)
-# Find commented line, if any, and remove leading '#'s
-define SYSTEM_REMOUNT_RW
-	$(SED) '/^#.*-o remount,rw \/$$/s~^#\+~~' $(TARGET_DIR)/etc/inittab
-endef
-else
-# Find uncommented line, if any, and add a leading '#'
-define SYSTEM_REMOUNT_RW
-	$(SED) '/^[^#].*-o remount,rw \/$$/s~^~#~' $(TARGET_DIR)/etc/inittab
+ifneq ($(BR2_INIT),)
+define FINALIZE_INIT
+	support/init/finalize $(BR2_INIT)
 endef
+TARGET_FINALIZE_HOOKS += FINALIZE_INIT
 endif
-TARGET_FINALIZE_HOOKS += SYSTEM_REMOUNT_RW
 
 endif # BR2_ROOTFS_SKELETON_DEFAULT
Signature · 1 line
2.0.3
#12 lore raw

RFC 4/11 help entries for Init system config menu

In reply to Alex Suykov

Primary focus is on (auto-)respawning and runtime control. Background/foreground distinction is not mentioned, since it is not likely to mean much for users making a choice here.

---
 system/Config.in | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)
system/Config.in +58 -0
index 9973cc2..c0ee345 100644
@@ -75,15 +75,46 @@ config BR2_TARGET_GENERIC_PASSWD_METHOD
 choice
 	prompt "Init system"
 	default BR2_INIT_BUSYBOX
+	help
+	  Upon bootup, kernel spawns init and init is expected
+	  to spawn anything else.
+
+	  Buildroot can pre-configure the target filesystem
+	  so that everything necessary to start the system
+	  is done and all installed daemons are started.
+
+	  There are several possible configurations providing
+	  varying degrees of control over the spawned processes.
 
 config BR2_INIT_BUSYBOX
 	bool "BusyBox"
 	select BR2_PACKAGE_BUSYBOX
+	help
+	  Minimalistic init implementation from busybox
+	  with systemV-style init scripts.
+
+	  No runlevel support.
+	  Daemons can be stopped or restarted at runtime.
+	  Daemons are started in background using scripts
+	  from /etc/init.d, and controlled using pid files.
+	  Failed processes are not respawned.
 
 config BR2_INIT_SYSV
 	bool "systemV"
 	select BR2_PACKAGE_BUSYBOX_SHOW_OTHERS # sysvinit
 	select BR2_PACKAGE_SYSVINIT
+	help
+	  System V init, probably the best-known init
+	  implementation in Linux, with simplified SysV-style
+	  initscripts.
+
+	  Supports runlevels, but this particular configuration
+	  does not use them.
+
+	  Daemons can be stopped or restarted at runtime.
+	  Daemons are started in background using scripts
+	  from /etc/init.d, and controlled using pid files.
+	  Failed processes are not respawned.
 
 config BR2_INIT_SYSTEMD
 	bool "systemd"
@@ -98,6 +129,27 @@ config BR2_INIT_SYSTEMD
 	depends on !BR2_STATIC_LIBS
 	depends on BR2_TOOLCHAIN_HEADERS_AT_LEAST_3_7
 	select BR2_PACKAGE_SYSTEMD
+	help
+	  systemd is more that just an init implementation.
+	  It is a composite package handling most aspects
+	  of system initialization and daemon supervision.
+
+	  All daemons will be started in foreground mode,
+	  configured to be respawed on failure.
+
+	  Systemd uses arbitrary-named "targets" instead
+	  of systemV-style runlevels, and allows stopping and
+	  restarting daemons at runtime using systemctl command.
+
+	  Due its pervasiveness and extensive feature range,
+	  choosing systemd shapes the rest of the system.
+	  A systemd-based buildroot will differ little
+	  from any major systemd-based Linux distribution
+	  in pretty much any aspects of the boot process,
+	  initialization, runtime configuration and process
+	  supervision.
+
+	  Beware of its large size and numerous dependencies.
 
 comment 'systemd needs an (e)glibc toolchain, headers >= 3.7'
 	depends on !(BR2_TOOLCHAIN_USES_GLIBC \
@@ -105,6 +157,12 @@ comment 'systemd needs an (e)glibc toolchain, headers >= 3.7'
 
 config BR2_INIT_NONE
 	bool "None"
+	help
+	  Do not install any kind of init system.
+
+	  Make sure your initrd and/or root fs skeleton provide
+	  some executable for kernel to start, otherwise
+	  the system will panic at boot.
 
 endchoice
 
Signature · 1 line
2.0.3
#13 lore raw

RFC 5/11 bare bb init configuration

In reply to Alex Suykov

This patch introduces a new init system: bb init without system V initscripts.

Busybox init is quite capable of running foreground daemons, with fast startup and auto-restarts but without the overhead of systemd. It lacks telinit and cannot start or stop daemons at runtime, but not every systems needs runtime control.

With the infrastructure mostly in place, implementing this is straightforward. Per-package initlines are installed in output/parts/ and init/finalize script picks them up to form a complete inittab.

Whenever a daemon needs some pre-start initialization and/or can not be started directly from inittab for other reasons, a shell script is created in /etc/rc/.

To keep things organized, initialization scripts (scripts that do not start a long-running foreground process) are put in /etc/rc/sys/ while anything directly in /etc/rc/ is expected to be used for :respawn: lines.

---
 package/Makefile.in      |  2 ++
 support/init/finalize    | 44 ++++++++++++++++++++++++-
 support/init/install-run | 83 ++++++++++++++++++++++++++++++++++++++++++++++--
 support/init/rc.sys/mdev |  4 +++
 support/init/rc.sys/udev |  8 +++++
 system/Config.in         | 16 ++++++++--
 6 files changed, 152 insertions(+), 5 deletions(-)
 create mode 100755 support/init/rc.sys/mdev
 create mode 100755 support/init/rc.sys/udev
package/Makefile.in +2 -0
index 599fe7f..df3b3b7 100644
@@ -412,6 +412,8 @@ ifdef BR2_INIT_SYSV
 BR2_INIT = initscripts
 else ifdef BR2_INIT_BUSYBOX
 BR2_INIT = initscripts
+else ifdef BR2_INIT_BUSYBOX_BARE
+BR2_INIT = inittab
 else ifdef BR2_INIT_SYSTEMD
 BR2_INIT = systemd
 else
support/init/finalize +43 -1

56 lines not on this page · raw message

support/init/install-run +81 -2

107 lines not on this page · raw message

support/init/rc.sys/mdev new file +4 -0
new file mode 100755
index 0000000..dd66441
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+echo /sbin/mdev >/proc/sys/kernel/hotplug
+exec /sbin/mdev -s
support/init/rc.sys/udev new file +8 -0
new file mode 100755
index 0000000..d5e40ea
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# udevd must be running by this point!
+
+printf '\000\000\000\000' > /proc/sys/kernel/hotplug
+udevadm trigger --type=subsystems --action=add
+udevadm trigger --type=devices --action=add
+udevadm settle --timeout=30
system/Config.in +14 -2
index c0ee345..d25ad85 100644
@@ -86,8 +86,20 @@ choice
 	  There are several possible configurations providing
 	  varying degrees of control over the spawned processes.
 
+config BR2_INIT_BUSYBOX_BARE
+	bool "BusyBox / inittab"
+	select BR2_PACKAGE_BUSYBOX
+	help
+	  Minimalistic init implementation from busybox.
+	  Daemons are written directly to /etc/inittab.
+
+	  No runlevel support.
+	  No runtime control over processes.
+	  Daemons are started in foreground mode,
+	  failed processes are respawned.
+
 config BR2_INIT_BUSYBOX
-	bool "BusyBox"
+	bool "BusyBox / initscripts"
 	select BR2_PACKAGE_BUSYBOX
 	help
 	  Minimalistic init implementation from busybox
@@ -100,7 +112,7 @@ config BR2_INIT_BUSYBOX
 	  Failed processes are not respawned.
 
 config BR2_INIT_SYSV
-	bool "systemV"
+	bool "sysvinit / initscripts"
 	select BR2_PACKAGE_BUSYBOX_SHOW_OTHERS # sysvinit
 	select BR2_PACKAGE_SYSVINIT
 	help
Signature · 1 line
2.0.3
#14 lore raw

RFC 6/11 ptp: new init infrastructure

In reply to Alex Suykov

Typical package: a simple foreground daemon.

---
 package/ptpd/S65ptpd  | 29 -----------------------------
 package/ptpd/ptpd.mk  |  5 -----
 package/ptpd/ptpd.run |  1 +
 3 files changed, 1 insertion(+), 34 deletions(-)
 delete mode 100755 package/ptpd/S65ptpd
 create mode 100644 package/ptpd/ptpd.run
package/ptpd/S65ptpd deleted +0 -29
deleted file mode 100755
index 4206c5e..0000000
@@ -1,29 +0,0 @@
-#!/bin/sh
-#
-# Start ptpd
-#
-
-case "$1" in
-  start)
-	echo -n "Starting ptpd: "
-	start-stop-daemon -S -q -x /usr/sbin/ptpd -- -S
-	if [ $? != 0 ]; then
-		echo "FAILED"
-		exit 1
-	else
-		echo "OK"
-	fi
-	;;
-  stop)
-	echo -n "Stopping ptpd: "
-	start-stop-daemon -K -q -x /usr/sbin/ptpd
-	echo "OK"
-	;;
-  restart|reload)
-	;;
-  *)
-	echo "Usage: $0 {start|stop|restart}"
-	exit 1
-esac
-
-exit $?
package/ptpd/ptpd.mk +0 -5
index ac9ab98..b08a5db 100644
@@ -17,9 +17,4 @@ define PTPD_INSTALL_TARGET_CMDS
 	$(INSTALL) -m 755 -D $(@D)/src/ptpd $(TARGET_DIR)/usr/sbin/ptpd
 endef
 
-define PTPD_INSTALL_INIT_SYSV
-	$(INSTALL) -m 755 -D package/ptpd/S65ptpd \
-		$(TARGET_DIR)/etc/init.d/S65ptpd
-endef
-
 $(eval $(generic-package))
package/ptpd/ptpd.run new file +1 -0
new file mode 100644
index 0000000..bf391c1
@@ -0,0 +1 @@
+exec /usr/sbin/ptpd -c -S
Signature · 1 line
2.0.3
#15 lore raw

RFC 7/11 upmpcli: new init infrastructure

In reply to Alex Suykov

Typical package: simple foreground daemon and its effective user entry.

---
 package/upmpdcli/S99upmpdcli    | 40 ----------------------------------------
 package/upmpdcli/upmpdcli.mk    |  9 ---------
 package/upmpdcli/upmpdcli.run   |  1 +
 package/upmpdcli/upmpdcli.users |  1 +
 4 files changed, 2 insertions(+), 49 deletions(-)
 delete mode 100644 package/upmpdcli/S99upmpdcli
 create mode 100644 package/upmpdcli/upmpdcli.run
 create mode 100644 package/upmpdcli/upmpdcli.users
package/upmpdcli/S99upmpdcli deleted +0 -40
deleted file mode 100644
index 07b10a6..0000000
@@ -1,40 +0,0 @@
-#!/bin/sh
-
-NAME=upmpdcli
-DAEMON=/usr/bin/$NAME
-CONFFILE=/etc/$NAME.conf
-PIDFILE=/var/run/$NAME.pid
-DAEMON_ARGS="-D -c $CONFFILE"
-
-# Sanity checks
-test -f $DAEMON || exit 0
-
-start() {
-        echo -n "Starting $NAME: "
-        start-stop-daemon --start --quiet --background --exec $DAEMON \
-                -- $DAEMON_ARGS \
-                && echo "OK" || echo "FAIL"
-}
-
-stop() {
-        echo -n "Stopping $NAME: "
-        start-stop-daemon --stop --quiet --pidfile $PIDFILE \
-                && echo "OK" || echo "FAIL"
-}
-
-case "$1" in
-        start)
-                start
-                ;;
-        stop)
-                stop
-                ;;
-        restart)
-                stop
-                sleep 1
-                start
-                ;;
-        *)
-                echo "Usage: $0 {start|stop|restart}"
-                exit 1
-esac
package/upmpdcli/upmpdcli.mk +0 -9
index 0be4d91..ab9e447 100644
@@ -10,15 +10,6 @@ UPMPDCLI_LICENSE = GPLv2+
 UPMPDCLI_LICENSE_FILES = COPYING
 UPMPDCLI_DEPENDENCIES = libmpdclient libupnpp
 
-# Upmpdcli only runs if user upmpdcli exists
-define UPMPDCLI_USERS
-	upmpdcli -1 upmpdcli -1 * - - - Upmpdcli MPD UPnP Renderer Front-End
-endef
-
-define UPMPDCLI_INSTALL_INIT_SYSV
-	$(INSTALL) -D -m 0755 package/upmpdcli/S99upmpdcli $(TARGET_DIR)/etc/init.d/S99upmpdcli
-endef
-
 define UPMPDCLI_INSTALL_CONF_FILE
 	$(INSTALL) -D -m 0755 $(@D)/src/upmpdcli.conf $(TARGET_DIR)/etc/upmpdcli.conf
 endef
package/upmpdcli/upmpdcli.run new file +1 -0
new file mode 100644
index 0000000..54bd8ec
@@ -0,0 +1 @@
+exec /usr/bin/upmpdcli
package/upmpdcli/upmpdcli.users new file +1 -0
new file mode 100644
index 0000000..c0adbd8
@@ -0,0 +1 @@
+upmpdcli -1 upmpdcli -1 * - - - Upmpdcli MPD UPnP Renderer Front-End
Signature · 1 line
2.0.3
#16 lore raw

RFC 8/11 acpid: new init infrastructure

In reply to Alex Suykov

Systemd has built-in support for acpi events and does not need acpid.

---
 package/acpid/S02acpid  | 22 ----------------------
 package/acpid/acpid.mk  |  5 -----
 package/acpid/acpid.run |  3 +++
 3 files changed, 3 insertions(+), 27 deletions(-)
 delete mode 100755 package/acpid/S02acpid
 create mode 100644 package/acpid/acpid.run
package/acpid/S02acpid deleted +0 -22
deleted file mode 100755
index 0840305..0000000
@@ -1,22 +0,0 @@
-#!/bin/sh
-
-case "$1" in
-	start)
-		echo -n "Starting acpid: "
-		start-stop-daemon -S -q -m -b -p /var/run/acpid.pid --exec /usr/sbin/acpid -- -n
-		[ $? = 0 ] && echo "OK" || echo "FAIL"
-		;;
-	stop)
-		echo -n "Stopping acpid: "
-		start-stop-daemon -K -q -p /var/run/acpid.pid
-		[ $? = 0 ] && echo "OK" || echo "FAIL"
-		;;
-	restart)
-		"$0" stop
-		sleep 1
-		"$0" start
-		;;
-	*)
-		echo "Usage: $0 {start|stop|restart}"
-		;;
-esac
package/acpid/acpid.mk +0 -5
index 7a6a478..61fc6c7 100644
@@ -10,11 +10,6 @@ ACPID_SITE = http://downloads.sourceforge.net/project/acpid2
 ACPID_LICENSE = GPLv2+
 ACPID_LICENSE_FILES = COPYING
 
-define ACPID_INSTALL_INIT_SYSV
-	$(INSTALL) -D -m 0755 package/acpid/S02acpid \
-		$(TARGET_DIR)/etc/init.d/S02acpid
-endef
-
 define ACPID_SET_EVENTS
 	mkdir -p $(TARGET_DIR)/etc/acpi/events
 	printf "event=button[ /]power\naction=/sbin/poweroff\n" \
package/acpid/acpid.run new file +3 -0
new file mode 100644
index 0000000..79c6216
@@ -0,0 +1,3 @@
+## ACPI daemon
+systemd -
+exec /usr/sbin/acpid -f -n
Signature · 1 line
2.0.3
#17 lore raw

RFC 9/11 am33x-cm3: new init infrastructure

In reply to Alex Suykov

Non-daemon entry.

---
 package/am33x-cm3/S93-am335x-pm-firmware-load | 6 ------
 package/am33x-cm3/am33x-cm3.mk                | 5 -----
 package/am33x-cm3/am33x-cm3.run               | 6 ++++++
 3 files changed, 6 insertions(+), 11 deletions(-)
 delete mode 100755 package/am33x-cm3/S93-am335x-pm-firmware-load
 create mode 100644 package/am33x-cm3/am33x-cm3.run
package/am33x-cm3/S93-am335x-pm-firmware-load deleted +0 -6
deleted file mode 100755
index 56c17b3..0000000
@@ -1,6 +0,0 @@
-#!/bin/sh
-
-# Load the PM CM3 firmware
-echo 1 > /sys/devices/ocp.2/44d00000.wkup_m3/firmware/am335x-pm-firmware.bin/loading
-cat /lib/firmware/am335x-pm-firmware.bin > /sys/devices/ocp.2/44d00000.wkup_m3/firmware/am335x-pm-firmware.bin/data
-echo 0 > /sys/devices/ocp.2/44d00000.wkup_m3/firmware/am335x-pm-firmware.bin/loading
package/am33x-cm3/am33x-cm3.mk +0 -5
index 01cb9a0..b00f6bb 100644
@@ -23,9 +23,4 @@ define AM33X_CM3_INSTALL_TARGET_CMDS
 		$(TARGET_DIR)/lib/firmware/am335x-pm-firmware.bin
 endef
 
-define AM33X_CM3_INSTALL_INIT_SYSV
-	$(INSTALL) -m 0755 -D package/am33x-cm3/S93-am335x-pm-firmware-load \
-		$(TARGET_DIR)/etc/init.d/S93-am335x-pm-firmware-load
-endef
-
 $(eval $(generic-package))
package/am33x-cm3/am33x-cm3.run new file +5 -0
new file mode 100644
index 0000000..68629a4
@@ -0,0 +1,5 @@
+## Load the PM CM3 firmware
+
+echo 1 > /sys/devices/ocp.2/44d00000.wkup_m3/firmware/am335x-pm-firmware.bin/loading
+cat /lib/firmware/am335x-pm-firmware.bin > /sys/devices/ocp.2/44d00000.wkup_m3/firmware/am335x-pm-firmware.bin/data
+echo 0 > /sys/devices/ocp.2/44d00000.wkup_m3/firmware/am335x-pm-firmware.bin/loading
Signature · 1 line
2.0.3
#18 lore raw

RFC 10/11 postgresql: new init infrastructure

In reply to Alex Suykov

One of the most complicated entries. Users, files, and pre-start initialization that must be done with a specific user id.

---
 package/postgresql/S50postgresql      | 44 -----------------------------------
 package/postgresql/postgresql.files   |  1 +
 package/postgresql/postgresql.mk      | 17 --------------
 package/postgresql/postgresql.run     |  6 +++++
 package/postgresql/postgresql.service | 24 -------------------
 package/postgresql/postgresql.users   |  1 +
 6 files changed, 8 insertions(+), 85 deletions(-)
 delete mode 100644 package/postgresql/S50postgresql
 create mode 100644 package/postgresql/postgresql.files
 create mode 100644 package/postgresql/postgresql.run
 delete mode 100644 package/postgresql/postgresql.service
 create mode 100644 package/postgresql/postgresql.users
package/postgresql/S50postgresql deleted +0 -44
deleted file mode 100644
index 86a8d83..0000000
@@ -1,44 +0,0 @@
-#!/bin/sh
-#
-# start postgresql
-#
-
-umask 077
-
-if [ ! -f /var/lib/pgsql/PG_VERSION ]; then
-	echo "Initializing postgresql data base..."
-	su - postgres -c '/usr/bin/pg_ctl initdb -D /var/lib/pgsql'
-	echo "done"
-fi
-
-start() {
-	echo -n "Starting postgresql: "
-	su - postgres -c '/usr/bin/pg_ctl start -D /var/lib/pgsql -l logfile'
-	echo "OK"
-}
-stop() {
-	echo -n "Stopping postgresql: "
-	su - postgres -c '/usr/bin/pg_ctl stop -D /var/lib/pgsql -m fast'
-	echo "OK"
-}
-restart() {
-	stop
-	start
-}
-
-case "$1" in
-	start)
-		start
-		;;
-	stop)
-		stop
-		;;
-	restart|reload)
-		restart
-		;;
-	*)
-		echo "Usage: $0 {start|stop|restart}"
-		exit 1
-esac
-
-exit $?
package/postgresql/postgresql.files new file +1 -0
new file mode 100644
index 0000000..81a3a25
@@ -0,0 +1 @@
+/var/lib/pgsql		d	0700	postgresql	postgresql	-	-	-	-	-
package/postgresql/postgresql.mk +0 -17
index bc382ce..1fbe1cf 100644
@@ -60,10 +60,6 @@ ifeq ($(BR2_PACKAGE_OPENSSL),y)
 	POSTGRESQL_CONF_OPTS += --with-openssl
 endif
 
-define POSTGRESQL_USERS
-	postgres -1 postgres -1 * /var/lib/pgsql /bin/sh - PostgreSQL Server
-endef
-
 define POSTGRESQL_INSTALL_TARGET_FIXUP
 	$(INSTALL) -dm 0700 $(TARGET_DIR)/var/lib/pgsql
 	$(RM) -rf $(TARGET_DIR)/usr/lib/postgresql/pgxs
@@ -78,17 +74,4 @@ endef
 
 POSTGRESQL_POST_INSTALL_STAGING_HOOKS += POSTGRESQL_INSTALL_CUSTOM_PG_CONFIG
 
-define POSTGRESQL_INSTALL_INIT_SYSV
-	$(INSTALL) -m 0755 -D package/postgresql/S50postgresql \
-		$(TARGET_DIR)/etc/init.d/S50postgresql
-endef
-
-define POSTGRESQL_INSTALL_INIT_SYSTEMD
-	$(INSTALL) -D -m 644 package/postgresql/postgresql.service \
-		$(TARGET_DIR)/usr/lib/systemd/system/postgresql.service
-	mkdir -p $(TARGET_DIR)/etc/systemd/system/multi-user.target.wants
-	ln -fs ../../../../usr/lib/systemd/system/postgresql.service \
-		$(TARGET_DIR)/etc/systemd/system/multi-user.target.wants/postgresql.service
-endef
-
 $(eval $(autotools-package))
package/postgresql/postgresql.run new file +6 -0
new file mode 100644
index 0000000..c7fcf36
@@ -0,0 +1,6 @@
+## PostgreSQL database server
+user postgres
+group postgres
+
+test -f /var/lib/pgsql/PG_VERSION || /usr/bin/initdb -D /var/lib/pgsql
+exec /usr/bin/postmaster -D /var/lib/pgsql
package/postgresql/postgresql.service deleted +0 -24
deleted file mode 100644
index 4a96258..0000000
@@ -1,24 +0,0 @@
-[Unit]
-Description=PostgreSQL database server
-After=network.target
-
-[Service]
-Type=forking
-
-# start timeout disabled because initdb may run a little
-# longer (eg. 5 minutes on RaspberryPi)
-TimeoutStartSec=0
-
-User=postgres
-Group=postgres
-
-SyslogIdentifier=postgres
-PIDFile=/var/lib/pgsql/postmaster.pid
-
-ExecStartPre=/bin/sh -c "if [ ! -f /var/lib/pgsql/PG_VERSION ]; then /usr/bin/pg_ctl initdb -D /var/lib/pgsql; fi"
-ExecStart=/usr/bin/pg_ctl start -D /var/lib/pgsql -w -l /var/lib/pgsql/logfile
-ExecReload=/usr/bin/pg_ctl reload -D /var/lib/pgsql
-ExecStop=/usr/bin/pg_ctl stop -D /var/lib/pgsql -m fast
-
-[Install]
-WantedBy=multi-user.target
package/postgresql/postgresql.users new file +1 -0
new file mode 100644
index 0000000..9724144
@@ -0,0 +1 @@
+postgres -1 postgres -1 * /var/lib/pgsql /bin/sh - PostgreSQL Server
Signature · 1 line
2.0.3
#19 lore raw

RFC 11/11 openvpn: new init infrastructure

In reply to Alex Suykov

The only case so far that install-run can not handle. Openvpn initscript spawns several processes, one for each configured tunnel.

Initscripts is the only system that allows this, primarily because it does not need to track spawned processes.

---
 package/openvpn/S60openvpn   | 103 -------------------------------------------
 package/openvpn/openvpn.init | 103 +++++++++++++++++++++++++++++++++++++++++++
 package/openvpn/openvpn.mk   |   5 ---
 package/openvpn/openvpn.run  |   1 +
 4 files changed, 104 insertions(+), 108 deletions(-)
 delete mode 100755 package/openvpn/S60openvpn
 create mode 100755 package/openvpn/openvpn.init
 create mode 100644 package/openvpn/openvpn.run
package/openvpn/S60openvpn deleted +0 -103
deleted file mode 100755
index 94bdc60..0000000
@@ -1,103 +0,0 @@
-#!/bin/sh -e
-#
-# Original version by Robert Leslie
-# <[email protected]>, edited by iwj and cs
-# Modified for openvpn by Alberto Gonzalez Iniesta <[email protected]>
-# Modified for restarting / starting / stopping single tunnels by Richard Mueller <[email protected]>
-
-test $DEBIAN_SCRIPT_DEBUG && set -v -x
-
-DAEMON=/usr/sbin/openvpn
-CONFIG_DIR=/etc/openvpn
-test -x $DAEMON || exit 0
-test -d $CONFIG_DIR || exit 0
-
-start_vpn () {
-    $DAEMON --daemon --writepid /var/run/openvpn.$NAME.pid \
-            --config $CONFIG_DIR/$NAME.conf --cd $CONFIG_DIR || echo -n " FAILED->"
-    echo -n " $NAME"
-}
-stop_vpn () {
-   kill `cat $PIDFILE` || true
-  rm $PIDFILE
-}
-
-case "$1" in
-start)
-  echo -n "Starting openvpn:"
-
-  if test -z $2 ; then
-    for CONFIG in `cd $CONFIG_DIR; ls *.conf 2> /dev/null`; do
-      NAME=${CONFIG%%.conf}
-      start_vpn
-    done
-  else
-    if test -e $CONFIG_DIR/$2.conf ; then
-      NAME=$2
-      start_vpn
-    else
-      echo -n " No such VPN: $2"
-    fi
-  fi
-  echo "."
-
-  ;;
-stop)
-  echo -n "Stopping openvpn:"
-
-  if test -z $2 ; then
-    for PIDFILE in `ls /var/run/openvpn.*.pid 2> /dev/null`; do
-      NAME=`echo $PIDFILE | cut -c18-`
-      NAME=${NAME%%.pid}
-      stop_vpn
-      echo -n " $NAME"
-    done
-  else
-    if test -e /var/run/openvpn.$2.pid ; then
-      PIDFILE=`ls /var/run/openvpn.$2.pid 2> /dev/null`
-      NAME=`echo $PIDFILE | cut -c18-`
-      NAME=${NAME%%.pid}
-      stop_vpn
-      echo -n " $NAME"
-    else
-      echo -n " No such VPN: $2"
-    fi
-  fi
-  echo "."
-  ;;
-# We only 'reload' for running VPNs. New ones will only start with 'start' or 'restart'.
-reload|force-reload)
-  echo -n "Reloading openvpn:"
-  for PIDFILE in `ls /var/run/openvpn.*.pid 2> /dev/null`; do
-    NAME=`echo $PIDFILE | cut -c18-`
-    NAME=${NAME%%.pid}
-# If openvpn if running under a different user than root we'll need to restart
-    if egrep '^( |\t)*user' $CONFIG_DIR/$NAME.conf > /dev/null 2>&1 ; then
-      stop_vpn
-      sleep 1
-      start_vpn
-      echo -n "(restarted)"
-    else
-      kill -HUP `cat $PIDFILE` || true
-#    start-stop-daemon --stop --signal HUP --quiet --oknodo \
-#      --exec $DAEMON --pidfile $PIDFILE
-    echo -n " $NAME"
-    fi
-  done
-  echo "."
-  ;;
-
-restart)
-  $0 stop $2
-  sleep 1
-  $0 start $2
-  ;;
-*)
-  echo "Usage: $0 {start|stop|reload|restart|force-reload}" >&2
-  exit 1
-  ;;
-esac
-
-exit 0
-
-# vim:set ai et sts=2 sw=2 tw=0:
package/openvpn/openvpn.init new file +103 -0

103 lines not on this page · raw message

package/openvpn/openvpn.mk +0 -5
index 3854b23..6937d50 100644
@@ -52,9 +52,4 @@ define OPENVPN_INSTALL_TARGET_CMDS
 		$(TARGET_DIR)/usr/sbin/openvpn
 endef
 
-define OPENVPN_INSTALL_INIT_SYSV
-	$(INSTALL) -m 755 -D package/openvpn/S60openvpn \
-		$(TARGET_DIR)/etc/init.d/S60openvpn
-endef
-
 $(eval $(autotools-package))
package/openvpn/openvpn.run new file +1 -0
new file mode 100644
index 0000000..20ce79c
@@ -0,0 +1 @@
+initscripts 60:openvpn.init
Signature · 1 line
2.0.3
#20 lore raw

cover common init infrastructure

In reply to Alex Suykov
Quoted 4 lines · Alex Suykov

This series is intended to clean up buildroot init system somewhat, removing the need for extensive sysv and systemd handling code in every package that installs init bits, and allowing alternative init systems to be implemented with reasonable amount of effort.

Wow, impressive. I hadn't imagined it would be possible to get this far.

I have a couple of overall remarks before I dive into the individual patches.

- Although we have a dependency on python, we don't currently use python for any of the core functionality (i.e., just building). Personally I like python a lot, but now you already have to know make and shell pretty well in order to touch the buildroot core. Adding python to the mix is making the threshold even higher.

- The generation script looks a bit complicated, while on the other hand the .run files are really terse. I'd prefer a bit more verbosity in the .run files, especially if that can make the generation script a bit simpler.

- The changes for .users and .files are pretty much independent from this series so they could be put in a separate series. And I'm anyway not convinced that they're worthwhile.

Regards,
Arnout

Quoted 35 lines

Overview of the changes:

* drop per-package sysv and systemd files, introduce common format used to generate files for both of them, use a script to do the conversion from common format to sysv or systemd.

* remove sysv and systemd installation code from package .mk files, let pkg-generic handle it.

* remove sysv-specific files from skeleton, and sysv-specific hacks from system/system.mk. Use a dedicated script to write inittab, handling global conditionals (root rw/ro, serial getty and so on)

* remove user definitions from package .mk files, and mkdirs from per-package sysv initscript, use per-package .users and .files instead in a way similar to .hash files.

Expected benefits:

* (almost) all packages get both sysv and systemd files at the same time and without the need to support them separately.

* init-related changes can be introduced without patching all 70+ individual packages that install startup files.

* new init systems can be introduced with only minor effort, including lightweight ones with controlled (foreground) daemons.

This series includes the infrastructure changes, and a couple of package patches to show how it looks like. Complete set of package patches uploaded here: https://github.com/arsv/br/

This series is for reviewing, not for merging.

Signature · 6 lines
Arnout Vandecappelle                          arnout at mind be
Senior Embedded Software Architect            +32-16-286500
Essensium/Mind                                http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium           BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F
#21 lore raw

cover common init infrastructure

Quoted 4 lines · Arnout Vandecappelle

- Although we have a dependency on python, we don't currently use python for any of the core functionality (i.e., just building). Personally I like python a lot, but now you already have to know make and shell pretty well in order to touch the buildroot core. Adding python to the mix is making the threshold even higher.

Ah, I see. I decided to go with python specifically to avoid extra dependencies, after looking at the language stats in support/scripts.
Now indeed python scripts there are not build scripts.

Quoted 3 lines

- The generation script looks a bit complicated, while on the other hand the .run files are really terse. I'd prefer a bit more verbosity in the .run files, especially if that can make the generation script a bit simpler.

Makes sense. And it may help to drop python dependency at some point. I need to think on this and maybe try things to see what could work better.

Initially the format was somewhat simplier, with prefixed lines. Definitely easier to parse, but there were some quirks with that approach.

#22 lore raw

cover common init infrastructure

In reply to Alex Suykov

Alex, All,

On 2015-03-21 20:26 +0200, Alex Suykov spake thusly:

Quoted 10 lines

This series is intended to clean up buildroot init system somewhat, removing the need for extensive sysv and systemd handling code in every package that installs init bits, and allowing alternative init systems to be implemented with reasonable amount of effort.

Overview of the changes:

* drop per-package sysv and systemd files, introduce common format used to generate files for both of them, use a script to do the conversion from common format to sysv or systemd.

I have not delve too deep in the implementation (because, Python! ;-) ), but from the examples, it seems it would still be possible to start more than one "daemon" for a service, like is done by samba, right?

Quoted 10 lines

* remove sysv and systemd installation code from package .mk files, let pkg-generic handle it.

* remove sysv-specific files from skeleton, and sysv-specific hacks from system/system.mk. Use a dedicated script to write inittab, handling global conditionals (root rw/ro, serial getty and so on)

* remove user definitions from package .mk files, and mkdirs from per-package sysv initscript, use per-package .users and .files instead in a way similar to .hash files.

How do you handle conditional creation of users/groups? Let's take a supposed package that can install a server and/or a client (like a SQL related package, for example). The server (sqld) needs a specific user+group, but the client (sql-cli) does not. Currently, this is easily done by emclosing the user defintion between a 'if server' block.

Quoted 8 lines

Expected benefits:

* (almost) all packages get both sysv and systemd files at the same time and without the need to support them separately.

* init-related changes can be introduced without patching all 70+ individual packages that install startup files.

Quoted 6 lines

* new init systems can be introduced with only minor effort, including lightweight ones with controlled (foreground) daemons.

This series includes the infrastructure changes, and a couple of package patches to show how it looks like. Complete set of package patches uploaded here: https://github.com/arsv/br/

It would be much nicer if you were to push your branch there, rather than a set of patches. Having a branch would mean we could fetch from it.

Quoted 1 line

This series is for reviewing, not for merging.

One thing that is wrong throughout the series, is that you hard-code the path to "outoput/" and this breaks out-of-tree builds [0]. You should use $(BASE_DIR) instead.

[0] http://buildroot.net/downloads/manual/manual.html#_building_out_of_tree

Also, I think this series is changing a lot of different things at the same time. For example, there is infra changes to handle:
- init script,
- users/groups,
- skeleton /etc/ stuff

This series should be split in simpler sub-series, or at least into much simpler patches. For example, patch 4/11 that adds help entries to init systems could probably sent first (after a bit of rewording to remove references to the new init infra), because it is a valuable addition, and it does not really depend on the new infra.

Otherwise, I have a feeling this is pushing things a bit too far. I'm usually very happy with "abstraction" and I more than once have pushed for such changes. However, in this area, I'm a bit sceptic as to whether we should introduce our own "initscript" format (the '.run' files).

Regards,
Yann E. MORIN.

Signature · 6 lines
.-----------------.--------------------.------------------.--------------------.
|  Yann E. MORIN  | Real-Time Embedded | /"\ ASCII RIBBON | Erics' conspiracy: |
| +33 662 376 056 | Software  Designer | \ / CAMPAIGN     |  ___               |
| +33 223 225 172 `------------.-------:  X  AGAINST      |  \e/  There is no  |
| http://ymorin.is-a-geek.org/ | _/*\_ | / \ HTML MAIL    |   v   conspiracy.  |
'------------------------------^-------^------------------^--------------------'
#23 lore raw

cover common init infrastructure

Quoted 5 lines · Yann E. MORIN

How do you handle conditional creation of users/groups? Let's take a supposed package that can install a server and/or a client (like a SQL related package, for example). The server (sqld) needs a specific user+group, but the client (sql-cli) does not. Currently, this is easily done by emclosing the user defintion between a 'if server' block.

I think it makes sense to install users unconditionally.
Mostly because not installing them is a minor optimization of the resulting rootfs image and I see no good way to handle it.

If necessary, perhaps listing .users to be included in the project .mk file may be an option, the same way it is done with .run files.

Quoted 4 lines

Otherwise, I have a feeling this is pushing things a bit too far. I'm usually very happy with "abstraction" and I more than once have pushed for such changes. However, in this area, I'm a bit sceptic as to whether we should introduce our own "initscript" format (the '.run' files).

That's a valid point, but I think buildroot already uses its own initscript format, namely its sysv(-style) initscripts.

They are supplied with buildroot, they are non-standard, and they are nearly useless outside of buildroot.

So I see it a choice between different formats for buildroot-specific service description, and the one currently in use does not look like a good data storage format at all.

#24 lore raw

cover common init infrastructure

Quoted 1 line · Alex Suykov

Sun, Mar 22, 2015 at 12:28:07PM +0100, Yann E. MORIN wrote:

[snip]

Quoted 7 lines
Quoted 4 lines

Otherwise, I have a feeling this is pushing things a bit too far. I'm usually very happy with "abstraction" and I more than once have pushed for such changes. However, in this area, I'm a bit sceptic as to whether we should introduce our own "initscript" format (the '.run' files).

That's a valid point, but I think buildroot already uses its own initscript format, namely its sysv(-style) initscripts.

Quoted 6 lines

They are supplied with buildroot, they are non-standard, and they are nearly useless outside of buildroot.

So I see it a choice between different formats for buildroot-specific service description, and the one currently in use does not look like a good data storage format at all.

The point is that the shell scripts provided by buildroot are just shell, so
"anyone" can understand and modify them. While the .run format is something new that nobody knows, and even if it is documented it will be non-trivial to find the documentation.

That's also why I say that the .run format should be verbose, to make it easy
to read and modify.

Regards,
Arnout

Signature · 6 lines
Arnout Vandecappelle                          arnout at mind be
Senior Embedded Software Architect            +32-16-286500
Essensium/Mind                                http://www.mind.be
G.Geenslaan 9, 3001 Leuven, Belgium           BE 872 984 063 RPR Leuven
LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle
GPG fingerprint:  7CB5 E4CC 6C2E EFD4 6E3D A754 F963 ECAB 2450 2F1F