Re: s6 usability

From: Colin Booth <colin_at_heliocat.net>
Date: Sat, 21 Dec 2019 21:19:14 +0000

On Sat, Dec 21, 2019 at 10:26:39AM +0100, Jan Braun wrote:
> > I hear you. Unfortunately, I have no control over what Debian does.
> > Debian isn't even able to ship a not-broken execline package, so I'm at
> > a loss on what to do with them. I'm working on a version of execline that
> > they *might* accept to package correctly,
>
> If you're referring to
> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=906250#37
> then, well, you are fighting against POSIX. There's little choice for
> Debian in the matter. Taking a hardline stance on such "legal" issues is
> part of their identity as a distro.
>
It doesn't help that neither Adam nor Jakub read the documentation for
the execline equivalents for cd, umask, or wait. That or they don't know
what 'execs into' means.
>
> > but it's doubtful as long as
> > the people in charge are prejudiced against the "lots of small binaries
> > in /bin" approach. :(
>
> I don't think that's the real issue. POSIX saying "the cd/umask/wait
> shell builtin must also be exec()able" is. Or execline's desire for
> binaries with those names and different behaviour, depending on your
> viewpoint.
>
Within the context of a shell the builtin will always* take precedence.

*I'm sure there's a way to break your shell so that it doesn't but I
don't know what it is and anyway it would be an impressively stupid
thing to do.
>
> > [... 3) ...]
> > The number of executables is a choice; I like to have more, smaller,
> > executables than less, bigger ones. [...]
> > So, I suppose it comes down to individual preference there.
>
> I agree, it's probably personal UI taste. To me, a good metric is the
> "fanout" of possible options:
> When I want to call something runit-related, I got
> * chpst: change process state
> ** -u: user
> ** -n: nofiles
> ...
> - sv: manipulate a service
> ** up
> ** down
> ** term
> ...
> - runsv<tab> supervision implemention
> ** runsv one service
> ** runsvdir a dir of services
>
> - sv-<tab> my custom scripts
> ** sv-errors show the readproctitle logs
> ...
>
> If any point in the tree, there's 7±2 children I can find by
> tab-completing/glancing at a man page, then I can probably navigate the
> whole thing pretty quickly.
>
> On the other hand:
> | $ ls /usr/bin/s6* | cut -d- -f 2 | uniq | wc -l
> | 39
> Even if there's still some related commands (e.g. 3x s6-sudo*), that
> number is not coming down to a point where I can keep everything in
> my head.
>
I think the real problem here is not that there are too many things
prefixed s6- but that there isn't a super clear delineation between
user-facing commands (s6-svc, s6-svscanctl, s6-svstat, s6-svok, s6-sudo,
s6-tai64nlocal), the portions that belong directly to the supervisor
(s6-svscan, s6-supervise, s6-ftrigrd), and the parts that are only used
occasionally or are meant to be called from inside of scripts (most
everything else). FWIW, runit is actually worse in terms of separating
out what goes where from a documentation standpoint, however there are
only nine programs shipped with runit so it matters less.
>
> But outside of supervision, I notice that you are reimplementing a
> lot of small programs. As long as they're mostly command-line compatible
> with their inspiration, I think such a "s6" executable would enable a
> nicer UI for s6-{linux,portable}-utils and the s6 djb reimplementations:
>
> Have your binaries in /usr/lib/s6/ (or wherever), and named without the
> "s6-" prefix. Have a "s6" binary multiplexing to these on its first
> argument. That way, a user can choose any of:
>
> | $ s6 cat foo
> |
> | $ PATH="/usr/lib/s6/:$PATH"
> | $ cat foo
> |
> | # ln -sf /usr/lib/s6/cat /bin/cat
> | $ cat foo
>
> (And possibly a s6-cat compatibility symlink somewhere.)
> This is similar to busybox (except for the reverse goal :) and allows
> individual customization, while keeping /bin/ uncluttered by default.
>
Have you ever considered slashpackage ;)

In all seriousness though this, with the exception of dropping the s6-
prefix (and the prefix-appender binary I guess), is what slashpackage
does. /bin stays uncluttered, commands end up in a PATH-able place, and
if you want to surprise any systemic shell scripts you have you can
symlink in replacements to the default PATH.
>
> > s6-rc, however, absolutely cannot do without execline, since it uses
> > autogenerated execline scripts. But s6-rc is a different beast, that
> > requires a lot more involvement than s6 anyway, and that isn't needed
> > at all if we're just talking about runit-like functionality.
>
> Yes. But since you are mentioning it, that was another of my "s6 seems
> more complex" issues. runit goes from "start the supervisor manually" to
> "be pid 1" with very little effort. See runit(8).
> Or https://www.unix.com/man-page/debian/8/runit/ I guess. ;-P
>
> s6-linux-init and s6-rc seem extremely complicated in comparison. And
> it's not clear to me how much of that complexity is optional, and what
> it might buy me. Maybe a better high-level overview document might help
> there.
>
If you're trying to have a drop-in replacement for runit(8) then
s6-linux-init (specifically s6-linux-init-maker) is all you really need
to figure out, and then only when building out a system. Then you need
to do some editing of the generated and relocated scripts to get it to
work right. Of course, setting up runit's 1 takes a bit of doing if you
want it to do anything else than put you into singleuser.

If you want a system that's modern (with service dependencies and all
that) you need to set up s6-rc but it is by no means a requirement.
s6-l-i on its own gets you a pretty compact boot system that's pretty
well suited for running purpose built VMs since you can handle all the
dependency tracking and shutdown protection using tools provided in s6
alone.

As for an overview, the why, overview, and quickstarts in s6-linux-init
should cover it. But for those who prefer it in email format, what you
get is: the supervisor as pid 1, hpr (halt/poweroff/reboot) interfaces
that understand how to work with the service model, direct IPC using
common s6 interfaces instead of the ghastly interfaces like stopit,
ctrlaltdel, reboot, nosync, a safety net of having a running supervisor
(and as such a running getty) during shutdown, and so on. runit is
impressively technically simple but that technical simplicity begats
workarounds and a lack of safety when it comes to the lifecycle of a
full system and most of the added design complexity around s6-l-i is
mostly there to make sure it can handle shutdown in a clean way.

FWIW, the original design of s6 followed much closer to the runit
design, though with stage1 execing into s6-svscan (instead of forking
it), stage2 only handling post boot initialization tasks (instead of
those tasks and then the supervisor), and stage3 also being pid1 (via
s6-svscan's finish script).

(speaking of walls of text).
>
> P.S: I stumbled over this execline oddity:
> | dollarat -0 -d a # separates by \0
> | forbacktickx -0 -d a var {gen...} loop... # splits on a
> IMHO, both should be an error, but at least treat them the same.
>
As per the docs for forbacktickx:
-0 : accept null characters from gen's output, using them as delimiters.
If this option and a -d option are used simultaneously, the rightmost
one wins.

Cheers!
-- 
Colin Booth
Received on Sat Dec 21 2019 - 21:19:14 UTC

This archive was generated by hypermail 2.3.0 : Sun May 09 2021 - 19:44:19 UTC