9 ms·
Runit – a Unix init scheme with service supervision
- atom_enger 11y agoRunit is amazing. I've used it on several large scale websites with great success. Runit follows the unix philosophy of being stupid simple and doing one thing incredibly well. If you're starting up a new project, consider using Runit.
- paulsmith 11y agoNot only is it simple and does the do-the-one-thing-well thing well, which is true, it's also _correct_. It's hard to overstate how valuable runit is in production because of that. It does the right thing with regard to clearing the environment, detaching from controlling terminal, logging, and many other subtle aspects of operating a service. I never worry about runit.
- dap 11y ago> Not only is it simple and does the do-the-one-thing-well thing well, which is true, it's also _correct_. How does it address the "who-watches-the-watcher" problem typically associated with service restarting?
- ori_b 11y agoMake it simple and obviously correct, and don't crash.
- dap 11y agoJust don't make any mistakes? Was that a joke? There are many reasons a process can die that are outside of its control, including signals from outside the process, handled (but uncorrectable) memory errors, and the OOM killer (on Linux). Besides that, it seems like a major design shortcoming if fatal errors in any particular program (however critical and however simple that program may be) can be unrecoverable for the whole system. It's definitely possible to solve this problem rigorously and completely, though I don't know of a way to do it without support from the kernel. On illumos systems, the service restarter ("svc.startd") provides a complex restart policy for user-defined services. I believe the restarter itself is restarted blindly by init, and init is restarted blindly by the kernel. If the kernel dies, the whole system is rebooted. In this way, if any software component in the chain of restarters fails, the system still converges to the correct state.
- ori_b 11y agoWhat if init doesn't exit, and just hangs? What if it just goes crazy and starts erronously restarting your processes? There are more failure modes than simply crashing. At some point, you just have to assume that some critical components are working correctly. Adding complexity just makes it harder to reason about it, or, depending on how paranoid you are, prove it.
- dap 11y agoThat's a slippery slope argument: because we can't solve the halting problem or verify program correctness, we shouldn't try to handle crashes, either? Agreed on minimizing complexity. The only part of the chain I described that's very complex is svc.startd, and that's largely to support rich configuration. Also don't mistake my position for saying that quality isn't important. Rather, just that perfection is not a reasonable constraint.
- vezzy-fnord 11y agoAt least on Linux, PID1's death is an instant kernel panic. As such, it's wise to keep any service management logic out of it. If the svscan process dies, then your system is still chugging along and you can intervene to restore the supervision tree (otherwise svscan inspects supervise processes at a regular 5s interval). If you have some really critical process, then you could integrate a checkpointer into the run script chain so that you can just pick off from the last image of the process state with minimal interruption.
- ori_b 11y ago> Also don't mistake my position for saying that quality isn't important. Rather, just that perfection is not a reasonable constraint. At some point, for some component or set of components, perfection is your only choice, regardless of the rest of your design. At least when you consider a single node with a single point of failure; this is less true for a distributed system where you have redundancy. At some point, you have to assume that either init is perfect, or that the code in the kernel to detect init failures is perfect, or that the watchdog monitoring the kernel is perfect, or whatever other layering you choose to put in place is perfect. In a system with a finite number of components, there is always going to be a point at which you just say "this bit is going to have to be correct, and there's no other way around it".
- freshhawk 11y agoBack when I changed from supervisord to runit my life was substantially improved. That correctness means way fewer emergency maintenance ops issues in production.
- general_failure 11y agoWhat is wrong with supervisord?
- freshhawk 11y agoFirst of all and mostly, we could never exactly figure it out what was going wrong. This was a few years ago and I don't remember all the details. We just had occasional issues with stopping/starting and especially restarting processes when pushing a new version out or when a process crashed. I do remember it could occasionally report a successful restart and still leave the old process(es) running. All my developers became very familiar with supervisord, and it was number 2 on the troubleshooting list (1. Did we introduce a bug in a recent commit? 2. Did supervisord do something weird again). After we switched to runit, only devs that touched ops knew about it at all. And we all forgot it was there. That's what you want in an ops tool.
- bnolsen 11y agoand additionally its totally understandable. its not scared of basic shell scripts and leveraging the wealth the posix environment provides.
- jflatow 11y agoRunit is / was awesome but how is this news?
- bitwize 11y agoMany people still think that it's a 3-way horse race between sysvinit, Upstart, and systemd (which systemd has all but won). The Debian technical committee certainly acted like that was the case last year.
- vezzy-fnord 11y agoA lot of people further neglect all the prior art in init replacements before those. The simpleinit dependency mechanism, depinit, initng, minit, daemond, Seth Nickell's GNOME experiments, eINIT, cinit and so forth. Instead, the way it was presented in public is that the Linux distros had been battling with brittle sysvinit scripts (true, but also largely self-inflicted) for so long until systemd came in to heroically save the day. It was pretty shocking to watch how the scene evolved from apathy to having an urgent problem that must be solved now.
- icebraining 11y agoWhat apathy? Ubuntu and Fedora had already switched to Upstart, and Gentoo to OpenRC, due to the problems identified with sysvinit.
- vezzy-fnord 11y agoOpenRC isn't an init daemon. It's only a process management framework, hence the name. It's usually used in conjunction with sysvinit as PID1. OpenRC was originally motivated by replacing the older baselayout scripts, from what I recall. Upstart didn't come about until later from many of the alternatives I listed, and its origins were mostly in response to launchd. It was quite rudimentary initially. [1] [1] https://wiki.ubuntu.com/ReplacementInit https://wiki.ubuntu.com/ReplacementInit
- clebio 11y agoGiven the other glowing comments, maybe this would be a place to ask: should I bother with Upstart, or Systemd? I see Shuttleworth announced the move to systemd, but it's not available on Ubuntu 14.04 servers right now. I'm writing provisioning for our production fleet, what should I use? The vagaries of the OS wars make something like Runit tempting.
- justizin 11y agoRunit is great for wrapping software that runs well in the foreground, but maybe doesn't handle being a daemon very well. This often goes for software written at / by a particular company, and software not written with large-scale use in mind. For system-level services, I usually stick with whatever the system I'm on does.
- vezzy-fnord 11y agoThere's no way of answering that question without knowing your exact requirements. However, if you want to preserve the extreme flexibility of the daemontools approach, but with a workflow that is systemd-like (even converting systemd unit files to native service bundles), check out the nosh project: http://homepage.ntlworld.com/jonathan.deboynepollard/Softwares/nosh.html http://homepage.ntlworld.com/jonathan.deboynepollard/Softwar...
- JoshTriplett 11y agoDepends heavily on what you need to provision, and whether you can select your provisioned environment based on what you want to support. Upstart is, at this point, effectively dead for any future distribution. However, if you want to support existing Ubuntu LTS distributions for the remainder of their lifetime, you'll need to handle it. Similarly, if you want to support the current rounds of enterprise distributions, you still need to support sysvinit. And if you have any non-Linux systems, you'll need to handle whatever they use as well. On the other hand, if you can ensure that your production systems all run relatively recent Linux distributions, you can safely assume systemd. Which specific distributions you have in production will determine the oldest version of systemd you have to support; since new features get added regularly, you'll want to know the oldest version you can assume. What are you trying to provision, and what requirements do you have?
- jlongster 11y agoNice to see daemontools-inspired work on HN in the past few days. I've been using runit for years, and as other comments have said, it's just not something I ever have to worry about. When I look around at other solutions it seems like I'd be taking a huge step back (making things more complex with arguably less usefulness). I've been meaning to do some blog posts about runit, as it seems like it sits on the back-burner in general. Does anyone know how actively it's maintained, or has it just reached such stability that it doesn't need much maintenance? It would neat to see it on github with some real docs and such.
- davexunit 11y agoI use GNU dmd instead. Simple and very extensible with Scheme. I use it as PID 1 on 2 of my machines, but I use another instance of it as a user service manager on all of my machines. I've also been meaning to replace runit with dmd in Phusion's passenger-docker image to get something more hackable. https://gnu.org/s/dmd https://gnu.org/s/dmd
- kragen 11y agoHaving dynamic memory allocation, let alone garbage collection, in my pid 1 doesn't sounds like a great idea. (I know, as long as I'm using Linux, I'm stuck with dynamic memory allocation in the fucking kernel. I don't have a plan for how to fix that yet.) (Also, thank you so much for all your help with Guix this last week!)
- blackbeard 11y agoThere's nothing wrong with dynamic allocation in a kernel. It is for example better than having fixed size process tables and all the crap that comes with that. "holy crap I've got to recompile my kernel to get more processes" is so 1995...
- kragen 11y agoYou know what else is "so 1995"? 400-day uptimes.
- blackbeard 11y agoNot really. I have centos boxes that have been up for over 3 years.
- jedisct1 11y agorunit is what the Phusion Docker base image http://phusion.github.io/baseimage-docker/ http://phusion.github.io/baseimage-docker/ is using, and it's the perfect tool to start and supervise containerized apps. I also love the fact that it can wait for a service to run (in order to wait for dependencies), and that stuck services can be restarted in a more radical way than a single TERM signal.
- explorer666 11y agoI'm using this too (after suffering all the other supervisors), and I have no clue why runit isn't the standard tool in Linux. Can any Linux expert explain that?
- vezzy-fnord 11y agoLinux is a kernel. It has no standards for userspace, though some have been attempted for GNU/Linux in particular and there are de facto conventions, but that's it.
- bnolsen 11y agotoo many politics going on, too many egos as well.
- manas952 11y agoRunit is fantastic. If you are using Chef - the runit cookbook integrates very nicely. https://supermarket.chef.io/cookbooks/runit https://supermarket.chef.io/cookbooks/runit
- atom_enger 11y agoNow that I think of it, the chef cookbook for Runit is what made it so easy to deploy to production. The 'runit_service' resource was absolutely invaluable. Forget the complicated upstart stanzas or dealing with supervisord, just write a shell script to run your program in the proper environment and ba! You've got a service!
- eddieroger 11y agoThis was how I got introduced to runit, and I couldn't agree more. It's really amazing at what it does, and quickly has become my favorite way of keeping processes running. It's just so easy.
- nathwill 11y agosince we're plugging init cookbooks, i'll plug a systemd cookbook[0] we're working on. would love some feedback from chef users using systemd-based systems! [0]: https://supermarket.chef.io/cookbooks/systemd https://supermarket.chef.io/cookbooks/systemd
- nisa 11y agoIf you run runit you can also take a look at runwhen: http://code.dogmap.org/runwhen/ http://code.dogmap.org/runwhen/ It's cron and at implemented in a quite elegant way. Unfortunately there does not seem to be much love for it in distributions. http://code.dogmap.org/runwhen/overview/#rationale http://code.dogmap.org/runwhen/overview/#rationale
- edwintorok 11y agoThere is a good comparison/documentation of what an init system like runit should do and why on the S6 site: http://skarnet.org/software/s6/why.html http://skarnet.org/software/s6/why.html http://skarnet.org/software/s6/overview.html http://skarnet.org/software/s6/overview.html Runit has the advantage that it is packaged in Debian and you can start using it right away.
- dkubb 11y agoDo you have any experience with S6? Do you know how it compares to runit?
- cathexis 11y agoI've used s6 a lot, though not as an init replacement in any systems that matter. As a supervisor I think it's great. For basic stuff (root process supervising supervisors supervising daemons) the two are basically identical with some superficial differences. For wider ranging stuff s6 is really good since it has a bunch of ancillary programs that solve a lot of serious issues in full system supervision (readyness notification vs polling in a run script, ucspi socket handing, etc).
- deleted 11y ago[deleted]
- cathexis 11y agoI missed actually answering the question about the difference between the two (plus, that comment is in dire need of editing and the edit window appears to have expired). The superficial differences are things like: service to logger pipe holding happens at different levels of the supervision tree (the root `s6-svscan' holds them in s6, the per-service runsv holds it in runit), `s6-svc -CMD behavior cannot currently be overridden whereas you can with `sv CMD', `s6-svscan' will immediately re-scan its directory with SIGALRM whereas `runsvdir' only polls for changes on a 5 second timer. For basic supervision tasksboth are great, with runit being the simpler of the two in terms of understanding what it gives out of the box. For larger tasks (full system supervision, inter-service ordering dependencies, etc) s6 has the tools to make that easy whereas with runit you're going to find yourself playing stupid tricks in run scripts to get similar behavior.
- lugus35 11y agoVoidlinux uses runit by default. http://www.voidlinux.eu http://www.voidlinux.eu
- stephen-mw 11y agoRunit is the default system daemon for Phusion's baseimage-docker Ubuntu image[0]. I've used it in a basic manner and have been very happy with it. For containers it hits a real sweet spot: lightweight and easy to use within a limited scope of processes. [0] https://github.com/phusion/baseimage-docker https://github.com/phusion/baseimage-docker
- kragen 11y agoI use runit. It's great. (Daemontools didn't have the ability to sleep for 30 seconds after my daemons crashed at startup because, like, some filesystem wasn't mounted or something.)
- Spiritus 11y agoHow did you manage that? We currently have a problem with crashing services using up all system resources trying to constantly restart. Or better yet, exponential backoff.
- ploxiln 11y agoIn the recent past I worked at a place that used daemontools extensively. We used a wrapper shell script which would do the restart loop detection, then exec the actual process to run. If it detected X restarts in Y seconds (by echoing the unix timestamp to a restart log and checking it) it would "svc -d $(dirname $0)" (or something like that) and exit. We also had a monitoring service (nagios) that would check if any services "auto-downed" on any servers and alert us.
- kragen 11y agorunit services have not only a 'run' but also an optional 'finish' script. My 'finish' script says #!/bin/sh sleep 30 I agree that exponential backoff would be better.
- idop 11y agoAnd just a friendly reminder that I wrote a shell for runit (and other daemontools-based supervisors) called svsh at https://ido50.github.io/Svsh https://ido50.github.io/Svsh.
- pchm 11y agoA genuine question, as it's not quite clear to me: can someone explain like I'm 5, what can I use runit for exactly? Is it a replacement for init.d or something more like monit? I always use monit to keep my Rails-related processes running and I've read somewhere that using monit combined with runit may be a better solution, but isn't it a bit redundant to have the two at the same time?
- mst 11y agorunit will start a daemon, and if it exits, restart it. i.e. you have runit sat 'atop' your daemon, as it were. monit checks for things, one of which is 'is the daemon running', and can then do things about it. runit to keep things that crash occasionally running and monit to keep an eye on general system health would seem totally sensical to me. (see also s6 which is another runit-like)
- cathexis 11y agoEssentially it's an alternative method for starting long running services (and restarting them if they fail). The things all daemontools-inspired process supervisors do: Runs a scanner gainst a service directory containing a directory for each program you want supervised (classically these are symlinks to another part of the system). The scanner spawns a supervisor program for every directory it finds which then looks for a program called `run' inside that directory and runs it as a foreground child. If the supervisor's child stops, it runs an optional script in it's supervision directory called `finish', and then runs run again. If one of the scanner's child supervisors stops, the scanner spawns it again. In runit's case, the scanner is called `runsvdir', the supervisors are called `runsv', and it also comes with a program called `runit' that can act as a replacement for your PID1 init whose sole job outside of boot and shutdown time is to resurrect runsvdir if it exits. Note that runsvdir is perfectly happy to be run via an entry in your /etc/inittab if you're running under sysvinit. At their most simplistic, that's all process supervision is - a bomb-proof way of keeping services running. All supervisors in the daemontools family come with a control program to interact with the process supervisor, as well as a stdin-based logger that doesn't rely on syslog. The main benefits it brings over the classic init.d/ model are simplicity (the most complex run script I have is 14 lines of dead simple shell, most are 4-5) and automatic restartability which init.d/ daemonization doesn't have. From what I understand from monit's manpage, it's a full-bore rule-basd system monitor. Generally speaking, process supervision is tacking one problem (keep daemons running), whereas monit is tacking another (system state monitoring). Yes monit can act as a process supervisor, but it does so by polling the system state and hooking into the existing daemonization infrastructure.