CLI tool
jordansissel/pleaserun avatar
jordansissel/pleaserun

Pleaserun: one command for systemd, upstart, launchd, runit and sysv init

An attempt to abstract this "init" script madness.

1,165 stars76 forksRubyNOASSERTION

At a glance

What is it?
Pleaserun is a Ruby tool that takes a program and a few options and writes the startup script or service definition for the init system on the machine it is running on, covering systemd, upstart, launchd, sysv init and runit. It suits an administrator who ships software that has to start correctly on more than one flavour of Unix, and it automates a job that is easy to get subtly wrong on each platform.
Who is it for?
Adopt Pleaserun if you maintain software that has to be installed as a service on more than one init system, because the tool detects the platform and writes the right unit, job or script instead of leaving you to hand port each one. Do not adopt it if you only ever deploy to systemd, since a hand written unit file is clearer than a generated one you have to read through a template to understand.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 151 days ago.
What is it written in?
Mainly Ruby, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem: every init system wants something different

The project description is an attempt to abstract this init script madness, and the README states the ambition directly. You should be able to specify a configuration of how to run a given service command, like apache or syslog-ng, and the tool should spit out a script or config file for your target platform.

That is a real and unglamorous problem. A service definition on systemd is a unit file with sections and directives, on upstart it is a job with events and a script stanza, on launchd it is a property list, on sysv init it is a shell script with a chkconfig header, and on runit it is a directory with a run script. Five formats, five sets of conventions, five places for a mistake that only shows up when the machine reboots.

The tool targets all five: launchd, upstart, systemd, runit and sysv init, and the project says it wants to be easy to extend and invites issues with ideas for more.

The three project principles are worth quoting because they explain the tone of the software. Community, and if a newbie has a bad time, it is a bug. Engineering, make it work, then make it right, then make it fast. And capabilities, if it does not do a thing today, we can make it do it tomorrow.

The first principle explains the tutorial style. The README walks through installing and building redis from a tarball, then generating a launcher for it, and it includes a lot of small asides. The README says the same principle again near the end: if you are having a bad time, it is a bug.

The flags, and how the platform is chosen

The overview section gives the basics, and the flags are small enough to remember.

The -p flag sets the platform to target. If it is not specified, the platform is detected automatically based on the current system and environment, and the tool prints what it found along with a warning level. The -v flag sets the version of the platform, which the documentation calls useful in cases where things like Upstart 0.6.5 differ wildly in configuration from Upstart 1.5. That is the reason version selection exists at all, and it is a good one, because an Upstart job that works on one generation fails on the other in ways that are hard to read.

The --name flag names the process, and the documentation explains where that name shows up. It becomes the name in /etc/init.d/the-name-you-give for sysv, and the name you use to reference the service with upstart, systemd or launchd.

The --prestart flag runs a command before starting the main program, and the use case given is configuration or validation checks before you start a program. If the prestart exits nonzero, the start of the process is aborted. That is the flag that turns the tool from a file generator into something you can put in a deployment pipeline.

The --install flag is the other important one. It tells pleaserun to install it on the current system, and the documentation is explicit that the default behaviour without it is to install into a temporary directory so you can copy it elsewhere if desired. The example also notes that you run it as root so it has permissions to write the files required for a service install.

The redis walkthrough, and what the output tells you

The first process example picks redis, and the framing is worth noting. The idea is to simulate the workflow you would normally go through in production, acquire software, deploy it, run it, and pleaserun helps with the run it part.

The setup builds redis from source and installs it under /tmp/redis, and the author explains why, this is just a demo.

code
wget http://download.redis.io/releases/redis-2.8.6.tar.gz
tar -zxf redis-2.8.6.tar.gz
cd redis-2.8.6
make -j4
make install PREFIX=/tmp/redis

Then the actual generation is one command, and the output is the interesting part because it tells you what the tool decided.

code
% sudo pleaserun --install /tmp/redis/bin/redis-server
No platform selected. Autodetecting... {:platform=>"upstart", :version=>"1.5", :level=>:warn}
No name given, setting reasonable default {:name=>"redis-server", :level=>:warn}
Writing file {:destination=>"/etc/init/redis-server.conf"}
Writing file {:destination=>"/etc/init.d/redis-server"}

Two decisions were made for you, and both are reported rather than hidden. The platform was detected as Upstart 1.5, and since no name was given, a reasonable default was chosen.

The result is that the service is up and answering, with the ps output showing the process with PPID 1, which is what a properly daemonised service looks like, and a redis-cli ping returning PONG. The recap is the three points that matter, that you ran the install command, that pleaserun detected the platform as Upstart 1.5, and that you did not have to write an init script or know how to write an Upstart config.

The prestart hook and the sysv example

The second example is shorter and shows the flags in combination, including the version selection for sysv.

code
% pleaserun --install -p sysv -v lsb-3.1 --name sleeper /bin/sleep 60
Writing file {:destination=>"/etc/init.d/sleeper"}
Writing file {:destination=>"/etc/default/sleeper"}

The version is given as lsb-3.1, which produces an LSB 3.1 compliant sysv style init script. The second file written, in /etc/default, is the conventional location for the configuration a sysv init script reads, so the tool writes both the script and its defaults file rather than baking values into the script.

The service is then used through the usual interface, with a status subcommand, a start subcommand, and a pid file in /var/run that the script writes.

code
% /etc/init.d/sleeper status
sleeper is not running

% sudo /etc/init.d/sleeper start
sleeper started.

The prestart hook is what makes this pattern safe in a deployment, and the documentation explains it in one sentence. You can run a command before starting the main program, and if the prestart exits nonzero the start of the process is aborted.

So the shape is a validation step that gates the service start. If your program needs a config file to be present and correct before it starts, that check goes in the prestart, and the service does not come up half configured.

How a platform is added, and what the templates hold

The repository layout shows how the platforms are organised, and it is a template driven design.

There is a templates directory holding the per platform templates, a lib directory with the Ruby code, a spec directory for the tests, a bin directory, and an examples directory whose single listed file is a runit example. The gemspec and Gemfile are at the root along with a rubocop configuration, a changelog in asciidoc, a Gemfile.lock and a Makefile.

The Makefile is interesting because it is a packaging pipeline rather than a build one. The version and the name are extracted by awk from the version file and the gemspec, and the targets build the gem, unpack it to check that the built gem is not faulty, install it locally, and push it. The test target runs the whole suite through a notify-failure script, and there is a testloop target that reruns the tests whenever a file changes, using inotifywait to watch the tree, and a serve-coverage target that serves the coverage directory with a simple Python HTTP server.

That structure is why adding a platform is described as a matter of contribution rather than of deep surgery. The template for the target system is added, the detection logic learns to recognise it, and the tests cover the generated output.

The upstream project runs on Ruby, and the hacking instructions are the classic ones, a decent Ruby through rvm, bundler, bundle install, bundle exec rspec, and a pull request.

The limits, and the state of the project

Two things to weigh before you adopt it.

The first is the nature of the abstraction. Pleaserun generates what each platform expects, and that means the result is only as good as the template. If your service needs something the template does not express, a platform specific behaviour, an unusual directive or a custom ordering, you are back to editing generated output by hand, which is the situation the tool was meant to remove. The escape hatch is a real constraint rather than a bug, and it applies to every generator.

There is also the question of whether you need it at all. If you deploy to one platform only, a hand written unit file is short, readable and reviewable, and a generated one is a file you have to learn to read through the generator's templates. The tool pays for itself when the same service has to be installed on several systems, or when you support several distributions with different init systems, which is the situation the project description is aimed at.

On the state of the project, the last push to the repository was on 2026-05-25, there are no tagged GitHub releases, and the version of the gem is the one that matters. The licence recorded for the repository is one that GitHub could not classify, so the LICENSE file at the root is what to read before shipping it in a product.

What has not changed is the ambition. The tool wants to be easy to extend, it wants new platforms to be a contribution rather than a redesign, and the third principle says that if it does not do a thing today, it can be made to do it tomorrow. For a project whose whole value is doing the boring part of five formats, that is the right posture.

Editorial conclusion

Adopt Pleaserun if you maintain software that has to be installed as a service on more than one init system, because the tool detects the platform and writes the right unit, job or script instead of leaving you to hand port each one. Do not adopt it if you only ever deploy to systemd, since a hand written unit file is clearer than a generated one you have to read through a template to understand. Before you run it with --install, read the template output first, because the default without that flag writes to a temporary directory and that is the safe way to see what it would do.

Frequently asked questions

What service managers does Pleaserun support?

It targets launchd, upstart, systemd, runit and sysv init. The platform is detected automatically from the current system and environment unless you set it with the -p flag, and the version can be set with -v, which matters because, for example, Upstart 0.6.5 differs widely in configuration from Upstart 1.5.

How do I install Pleaserun?

With gem install pleaserun. Running it with --install writes the files to the real system and needs root, while the default without that flag installs into a temporary directory so you can inspect or copy the result elsewhere.

What does the --prestart option do in Pleaserun?

It runs a command before the main program starts, which the documentation suggests for configuration or validation checks. If the prestart command exits nonzero, the start of the process is aborted.

How do I run the Pleaserun tests?

The hacking instructions are to get a decent Ruby, install bundler, run bundle install, and run the tests with bundle exec rspec. The Makefile also has a test target that runs the suite and a testloop target that reruns it whenever files change, using inotifywait to watch the tree.

Official sources

  1. Issues
  2. jordansissel/pleaserun on GitHub
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jordansissel-pleaserun.svg)](https://hysenlabs.com/projects/jordansissel-pleaserun)

Was this useful?