S6-RC-UPDATE(8)

πŸ“¦ version 0.7.0.0, in nixpkgs unstable

πŸ’… s6-rc-update(8) β€” the online service database switcher πŸ’…

okay so bestie, listen up: this is s6-rc-update from the System Manager's Manual, and it's genuinely the glow-up tool for your service database. no reboots, no drama. let's go ✨


🌸 SYNOPSIS 🌸

s6-rc-update [-n] [-v verbosity] [-t timeout] [-l live] [-f convfile]
             [-b] [-e | -E] newdb

πŸ¦‹ DESCRIPTION πŸ¦‹

so s6-rc-update is an online service database switcher β€” it literally replaces your compiled service database with a different one and then adjusts the live state to match. it's giving "change your whole set of services without ever rebooting" energy. iconic. πŸ‘‘

ngl though, live-upgrading a service database is not easy, and no fully automated system can get it right in every single case. s6-rc-update will do its absolute best on its own, but it also lets you hand it instructions for the tricky cases. and instead of implementing doubtful heuristics (no cap, that's what the manpage says), it will just fail with an error message in situations it can't solve. honest king behavior fr fr πŸ’―

here's the whole vibe of what it does:

  • it analyzes the current live state, the current compiled service database, and the compiled service database contained at newdb (which must be an absolute path).
  • additionally, it can process an optional conversion file containing instructions.
  • it computes the necessary service transitions to safely update the live database.
  • it shuts down the necessary services.
  • it updates the live directory so that newdb becomes the live compiled service database.
  • it starts up the necessary services.

πŸ”„ Transition details πŸ”„

so the whole job of s6-rc-update is to ensure consistency of the live state across a change of compiled service databases. to do that, it has to make sure that the services that are up at the time of its invocation are still up after its invocation. but bestie, the service definitions in the new compiled might be totally different from the old one β€” especially the dependencies can change, or a service can straight-up change types: a oneshot can become a longrun and vice-versa, and an atomic service can even become a bundle. the range. 😭

πŸͺž Service identity πŸͺž

s6-rc-update examines atomic services, as defined in the old compiled, that are up at invocation time, and computes what's necessary for the "same" services, as defined in the new compiled, to be up. barring instructions from the conversion file, the service is "the same" if it has the same name in the new compiled β€” no matter its type. periodt.

so like: if there's an up oneshot named sshd in the old compiled, and there's a longrun named sshd in the new compiled, then s6-rc-update will decide that the new sshd longrun will replace the old sshd oneshot. and if the new compiled defines an sshd bundle instead, then s6-rc-update will decide that the old sshd oneshot will be replaced with the contents of the sshd bundle. slay, seamless. ✨

πŸ” Restarts πŸ”

s6-rc-update tries to avoid needlessly restarting services β€” like, running it with a new compiled that's an exact copy of the old compiled should cause zero restarts. so chill. 🧘

it will flag a service to be restarted in these cases:

  • the service has disappeared in the new compiled. in this case, the old service will simply be stopped.
  • the service has changed types: a oneshot becomes a longrun, a longrun becomes a oneshot, or an atomic service becomes a bundle. in this case, the old service will be stopped, then the new service will be started.
  • the service has a dependency to a service that must restart, or to an old service that must stop, or to a new service that did not previously exist or that was previously down.
  • there's an instruction to restart the service in the conversion file.

πŸͺœ Steps πŸͺœ

after it has decided which services it should restart, s6-rc-update will:

  • invoke s6-rc(8) to stop old services.
  • update the live directory with the data from the new compiled. ⚠️ this is the critical part β€” s6-rc-update should not be interrupted at this point. it does its best to avoid risking leaving behind an inconsistent state, but a 100% atomicity guarantee is impossible to achieve. so like, please don't Ctrl+C it here, bestie, i'm begging πŸ™
  • adjust pipe names for the existing pipelines, if needed.
  • exec into s6-rc(8) to start new services.

πŸ“ The conversion file πŸ“

the conversion file is used to give s6-rc-update instructions when the change of databases isn't entirely straightforward. currently, it supports these features:

  • changing the name of a service.
  • forcing a restart on a service.

πŸ“„ Format πŸ“„

the conversion file is a sequence of lines; each line is parsed independently β€” there's no carrying of information from one line to the next. each line is its own little main character. πŸ’«

a line is lexed into words by the execlineb(1) lexer, which means that words are normally separated by whitespace, but can be quoted, that # comments are recognized, etc. classic.

the first word in a line must be the name of an "old" atomic service, i.e. an atomic service contained in the current live database. the remaining words in the line are instructions telling s6-rc-update how to convert that service.

✏️ Renaming ✏️

if the second word in the line is ->, then the third word in the line must be the new name of the service in the new database: s6-rc-update will then rename it. it's possible to rename an atomic service to another atomic service or to a bundle, but no matter whether a service is renamed or not, changing its type will force a restart. iykyk. πŸŽ€

πŸ”ƒ Restarting πŸ”ƒ

if the word following either the old name, or a renaming instruction, is the word restart, then the service will be forced to restart. simple as that. πŸ’…


πŸ—‚οΈ Safely managing and updating compiled databases πŸ—‚οΈ

the sequence of operations needed to update a database from source to live can be a little tricky. it involves:

  • compiling the new database without overwriting the live one.
  • calling s6-rc-update to safely replace the live database.
  • making sure the new database will be correctly used at boot time.

the FAQ entry at [1] gives a step-by-step explanation on how to proceed. go read it, bestie. 🫢


🧠 Notes 🧠

the live argument to the -l option, if present, should be the same argument that was given to the s6-rc-init(8) invocation when the system was booted. in other words: it should be the name of the symbolic link pointing to the real directory containing the live information, not the name of the real directory. don't get it twisted. πŸ™ˆ

if a longrun service is renamed from oldname to newname, but not restarted, the s6-supervise(8) process in charge of it will still show up in the process list as s6-supervise oldname. this is purely cosmetic and will have no impact on the service; nevertheless, if you wish to avoid that, simply force a restart on every longrun you rename. aesthetic choice, honestly. πŸ’…

after an s6-rc-update invocation, the old compiled service database is left unchanged where it was, and the new compiled service database is used in-place. if the machine is rebooted, the s6-rc-init(8) invocation will still boot on the old compiled unless more work is performed. it's recommended to keep a current symbolic link to the current compiled, to always s6-rc-init(8) on current, and to make current a link to the new compiled right after an s6-rc-update invocation. yes, that's three separate things. do all three. πŸ“Œ

s6-rc-update is the only way to "free" the old compiled database for displacement or deletion. a live compiled database must not be tampered with. after an s6-rc-update invocation, the old database isn't live anymore and can be moved or deleted; instead, newdb is live. okurrr. πŸ”₯


✨ OPTIONS ✨

  • -n, --dry-run β€” dry run. s6-rc-update will compute the service transitions, and print the s6-rc(8) command lines it would execute to perform those transitions. it will not actually run them or modify the live database. it's giving window shopping πŸ›οΈ
  • -v verbosity, --verbosity=verbosity β€” be more or less verbose. default is 1: warning and error messages will be printed to stderr. 0 silences warnings. 2 adds a bit more information about what s6-rc-update is doing. 3 or more is heavy debug output. choose your fighter. πŸ“’
  • -t timeout, --timeout=timeout β€” if s6-rc-update cannot perform its job within timeout milliseconds, it will exit. the default is 0, meaning infinite (no timeout). ⚠️ be aware that timing out and exiting may leave the live database in an inconsistent state, so use of this option is not recommended. seriously, leave it alone. πŸ’€
  • -l live, --livedir=live β€” look for the live state in live. it must be an absolute path. default is /run/s6-rc. the default can be changed at compile-time by giving the --livedir=live option to ./configure. πŸ› οΈ
  • -f convfile, --conversion-file=convfile β€” use the conversion file located at convfile. default is /dev/null, meaning no special instructions. πŸ“„
  • -b, --block β€” blocking lock. if the database is currently being used by another program, s6-rc-update will wait until that other program has released its lock on the database, then proceed. by default, s6-rc-update fails with an error message if the database is currently in use. so -b is the "i'll wait, bestie" flag. πŸ•°οΈ
  • -E, --no-force-essentials β€” if essential services are scheduled to be stopped for the transition, ignore them, i.e. keep them alive. this is the default. πŸ›‘οΈ
  • -e, --force-essentials β€” if essential services are scheduled to be stopped for the transition, stop them just like any other service. bold move. πŸ”₯

🚦 EXIT STATUS 🚦

  • 0 β€” success. slay. βœ…
  • 1 β€” failure to perform some state transitions, but the database was switched to newdb.
  • 2 β€” timed out, but the database was switched to newdb.
  • 3 β€” unknown service name in the conversion file.
  • 4 β€” invalid service database.
  • 5 β€” wrong service type in the conversion file.
  • 6 β€” duplicate service in the conversion file.
  • 9 β€” failure to perform some state transitions, and the database was not switched.
  • 10 β€” timed out, and the database was not switched.
  • 100 β€” wrong usage.
  • 111 β€” system call failed.
  • 126 β€” cannot exec into s6-rc(8) for the final "up" transition (error other than ENOENT).
  • 127 β€” cannot exec into s6-rc(8) for the final "up" transition (executable not found).

🌈 EXAMPLES 🌈

consider the following conversion file:

# Simple conversion file
mount-var -> mount-rwfs
httpd restart
sqld -> mysqld restart

here's what that does, line by line, bestie:

  • it will rename mount-var to mount-rwfs, not restarting it if mount-var in the old database and mount-rwfs in the new database have the same type and do not depend on services that would force a restart.
  • it will restart httpd.
  • it will rename sqld to mysqld and make it restart.

ate that up. πŸ“


πŸ‘€ SEE ALSO πŸ‘€

s6-rc-faq(7), s6-rc-overview(7), s6-rc-why(7), s6-rc(8), s6-rc-bundle(8), s6-rc-compile(8), s6-rc-db(8), s6-rc-dryrun(8), s6-rc-fdholder-filler(8), s6-rc-format-upgrade(8), s6-rc-init(8), s6-rc-oneshot-run(8)

this man page is ported from the authoritative documentation at: https://skarnet.org/software/s6-rc/s6-rc-update.html


πŸ’– to be continued... part 2 is on its way, don't touch that dial πŸ’–

🌸 AUTHORS 🌸

Okay so this page was literally a group project, and we're giving credit where credit is due, bestie πŸ’–

  • Laurent Bercot β€” the actual mastermind behind it all πŸ‘‘ the main character of this whole s6 situation, no cap.
  • Alexis <flexibeast@gmail.com> β€” did the man page port πŸŽ€ aka the person who made sure you (yes, you) could read all of this in proper manpage form. Iconic behaviour, honestly.

and that's a wrap on the whole page, omg πŸ¦‹ go forth and update your services, you absolute legend πŸ’…

This one came to you from Debian, dated January 24, 2026 β€” that's the S6-RC-UPDATE(8) manual page, in the flesh, section 8, system administration girlie through and through ✨ love that for us 🫢
πŸ“¦ where this page comes from