What is the correct substitute for rc.local in systemd instead of re-creating rc.local
As pointed out elsewhere, it becomes moderately unclean to use rc-local.service
under systemd
.
- It is theoretically possible that your distribution will not enable it. (I think this is not common, e.g. because disabling the same build option also removes
poweroff
/reboot
commands that a lot of people use). - The semantics are not entirely clear. Systemd defines
rc-local.service
one way, but Debian provides a drop-in file which alters at least one important setting.
rc-local.service
can often work well. If you're worried about the above, all you need to do is make your own copy of it! Here's the magic:
# /etc/systemd/system/my-startup.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/libexec/my-startup-script
[Install]
WantedBy=multi-user.target
I don't think you need to understand every single detail[*], but there are two things you need to know here.
You need to enable this with
systemctl enable my-startup.service
.If your script has a dependency on any other service, including
network-online.target
, you must declare it. E.g. add a[Unit]
section, with the linesWants=network-online.target
andAfter=network-online.target
.You don't need to worry about dependencies on "early boot" services - specifically, services that are already ordered before
basic.target
. Services likemy-startup.service
are automatically ordered afterbasic.target
, unless they setDefaultDependencies=no
.If you're not sure whether one of your dependencies is an "early boot" service, one approach is to list the services that are ordered before
basic.target
, by runningsystemctl list-dependencies --after basic.target
. (Note that's--after
, not--before
).
There are some considerations that I think also applied to pre-systemd rc.local
:
- You need to make sure your commands are not conflicting with another program that tries to control the same thing.
- It is best not to start long-running programs aka daemons from
rc.local
.
[*] I used Type=oneshot
+ RemainAfterExit=yes
because it makes more sense for most one-shot scripts. It formalizes that you will run a series of commands, that my-startup
will be shown as "active" once they have completed, and that you will not start a daemon.
Forget about rc.local
.
As I said about CentOS 7 and about Debian 8 and about Ubuntu 15:
You're using a systemd+Linux operating system. /etc/rc.local
is a double backwards compatibility mechanism in systemd, because it is a backwards compatibility mechanism for a mechanism that was itself a compatibility mechanism in the van Smoorenburg System 5 rc
clone.
Using /etc/rc.local
can go horribly wrong. People have been surprised by the fact that systemd doesn't run rc.local
in quite the same way, in quite the same place in the bootstrap, as they are used to. (Or erroneously expect: It did not, in fact, run last in the old system, as the OpenBSD manual still points out.) Others have been surprised by the fact that what they set up in rc.local
expecting the old ways of doing things, is then completely undone by the likes of new udev
rules, NetworkManager, systemd-logind
, systemd-resolved
, or various "Kit"s.
As exemplified by "Why does `init 0` result in "Excess Arguments" on Arch install?", some operating systems already provide systemd without the backwards compatibility features such as the systemd-rc-local-generator
generator. Whilst Debian still retains the backwards compatibility features, Arch Linux builds systemd with them turned off. So on Arch and operating systems like it expect /etc/rc.local
to be entirely ignored.
Forget about rc.local
. It's not the way to go. You have a systemd+Linux operating system. So make a proper systemd service unit, and don't begin from a point that is two levels of backwards compatibility away. (On Ubuntu and Fedora, it is three times removed, the van Smoorenburg System 5 rc
clone that followed rc.local
having then been itself twice superseded, over a decade ago, first by upstart and then by systemd.)
Also remember the first rule for migrating to systemd.
This is not even a new idea that is specific to systemd. On van Smoorenburg rc
and Upstart systems, the thing to do was to make a proper van Smoorenburg rc
script or Upstart job file rather than use rc.local
. Even FreeBSD's manual notes that nowadays one creates a proper Mewburn rc
script instead of using /etc/rc.local
. Mewburn rc
was introduced by NetBSD 1.5 in 2000.
/etc/rc.local
dates from the time of Seventh Edition Unix and before. It was superseded by /etc/inittab
and a runlevel-based rc
in AT&T Unix System 3 (with a slightly different /etc/inittab
in AT&T Unix System 5) in 1983. Even that is now history.
Create proper native service definitions for your service management system, whether that be a service bundle for the nosh toolset's service-manager
and system-control
, an /etc/rc.d/
script for Mewburn rc
, a service unit file for systemd, a job file for Upstart, a service directory for runit/s6/daemontools-encore, or even an /etc/init.d/
script for van Smoorenburg rc
.
In systemd, such administrator-added service unit files go in /etc/systemd/system/
usually (or /usr/local/lib/systemd/system/
rarely). With the nosh service manager, /var/local/sv/
is a conventional place for local service bundles. Mewburn rc
on FreeBSD uses /usr/local/etc/rc.d/
. Packaged service unit files and service bundles, if you are making them, go in different places, though.
Further reading
- Lennart Poettering et al. (2014). systemd-rc-local-generator. systemd manual pages. Freedesktop.org.
rc.local
. FreeBSD System Manager's Manual. 2016-04-23.- https://unix.stackexchange.com/a/233581/5132
- Lennart Poettering (2011-08-29). Plese remove
/etc/rc.local
orchmod -x
it. Redhat bug #734268. - https://unix.stackexchange.com/a/211927/5132
- Dirk Schmitt (2017-12-19).
rc.local
is starting to early. systemd bug #7703 - https://wiki.archlinux.org/index.php?title=Systemd&diff=378926&oldid=378924
- Benjamin Cane (2011-12-30). When it's Ok and Not Ok to use
rc.local
. bencane.com. - https://unix.stackexchange.com/a/49636/5132
- Lennart Poettering (2010-10-01). How Do I Convert A SysV Init Script Into A systemd Service File?. 0pointer.de.
- https://askubuntu.com/questions/523369/
- Jonathan de Boyne Pollard (2015).
/etc/inittab
is a thing of the past.. Frequently Given Answers. - Jonathan de Boyne Pollard (2014). A side-by-side look at run scripts and service units.. Frequently Given Answers.
- Jonathan de Boyne Pollard (2014). A real-world worked example of setting up and running a service with nosh. Softwares.
- Jonathan de Boyne Pollard (2016). "Missing system search paths from the
systemd.unit
manual page". Errata for systemd doco. Frequently Given Answers.
Summary of https://www.linuxbabe.com/linux-server/how-to-enable-etcrc-local-with-systemd
Create /etc/systemd/system/rc-local.service:
# /etc/systemd/system/rc-local.service
[Unit]
Description=/etc/rc.local Compatibility
ConditionPathExists=/etc/rc.local
[Service]
Type=forking
ExecStart=/etc/rc.local start
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
SysVStartPriority=99
[Install]
WantedBy=multi-user.target
Then:
sudo touch /etc/rc.local
sudo chmod +x /etc/rc.local
sudo systemctl enable rc-local
Check with:
sudo systemctl start rc-local.service
sudo systemctl status rc-local.service