Tutorial details | |
---|---|
Difficulty | Easy (rss) |
Root privileges | Yes |
Requirements | Linux with systemd as init |
Time | 5m |
Enabling rc.local shell script on systemd while booting Linux system
/etc/rc.local compatibility achieved on systemd using special service called rc-local.service. This unit gets called automatically into multi-user.target by systemd-rc-local-generator if /etc/rc.local is executable.
Executing rc.local shell script during boot using systemd
Naturally, create or update/edit the file named /etc/rc.local using your favorite text editor. I am going to use vim command:
$ sudo vim /etc/rc.local
## RHEL/CentOS/Fedora Linux edit the /etc/rc.d/rc.local ##
$ sudo vim /etc/rc.d/rc.local
Append required commands or call script. Here is my file:
#!/bin/sh # add your commands # call your scripts here # let us set stuff for my wifi /sbin/iw phy0 wowlan enable magic-packet disconnect # last line must be exit 0 exit 0
Save and close the file when using vim. Make sure you set executable permission using the chmod command:
$ sudo chmod -v +x /etc/rc.local
Turing on rc-local.service on Linux when systemd is init
All we need to do is type the following systemctl command:
$ sudo systemctl enable rc-local.service
Reboot the Linux box:
$ sudo reboot
Verify status after reboot:
$ sudo systemctl status rc-local.service
Here is what we see on screen:
● rc-local.service - /etc/rc.local Compatibility Loaded: loaded (/etc/systemd/system/rc-local.service; enabled-runtime; ven> Drop-In: /usr/lib/systemd/system/rc-local.service.d └─debian.conf Active: active (exited) since Wed 2020-11-04 13:29:54 IST; 1h 59min ago Docs: man:systemd-rc-local-generator(8) Tasks: 0 (limit: 37939) Memory: 0B CGroup: /system.slice/rc-local.service Nov 04 13:29:54 nixcraft-wks01 systemd[1]: Starting /etc/rc.local Compatibility Nov 04 13:29:54 nixcraft-wks01 systemd[1]: Started /etc/rc.local Compatibility.
See how to view status of a service on Linux using systemctl command for more info.
How to see service configuration
Open the terminal app and then type:
$ sudo systemctl cat rc-local.service
We see systemd configuration as follows:
# /etc/systemd/system/rc-local.service # SPDX-License-Identifier: LGPL-2.1+ # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # This unit gets pulled automatically into multi-user.target by # systemd-rc-local-generator if /etc/rc.local is executable. [Unit] Description=/etc/rc.local Compatibility Documentation=man:systemd-rc-local-generator(8) ConditionFileIsExecutable=/etc/rc.local After=network.target [Service] Type=forking ExecStart=/etc/rc.local start TimeoutSec=0 RemainAfterExit=yes GuessMainPID=no # /usr/lib/systemd/system/rc-local.service.d/debian.conf [Unit] # not specified by LSB, but has been behaving that way in Debian under SysV # init and upstart After=network-online.target # Often contains status messages which users expect to see on the console # during boot [Service] StandardOutput=journal+console StandardError=journal+console
Note: Run sudo SYSTEMD_LOG_LEVEL=debug /usr/lib/systemd/system-generators/systemd-rc-local-generator to debug /etc/rc.local issues when script is not loading.
A note about runlevels
Back in the days when init was the default, we had different runlevels as follows:
- S – Boot the Linux system
- 0 – Shutdown the Linux box
- 6 – Reboot the Linux
- 1 – Linux Single-user mode used for recovering Linux system in an emergency mode
- 2 to 5 – Normal operation multiuser system that supported both CLI and GUI and full networking
Often Linux distros and Unix system modified these runlevel values as per their needs. However, /etc/rc.local got called when the system entered multiuser mode via runlevel 2 to 5. However, this default was removed when the majority of Linux distro switched to systemd. Hence, I wrote this quick guide for Linux developers and system administrators.
Creating your own service is easy with systemd on Linux
Instead of shell script in /etc/rc.d/ or call /etc/rc.local we do this now. It only works on Linux and not other Unix variants. Then you just do:
# /etc/systemd/system/my-service-name-goes-here.service # # Sample template to call your script or command when systemd boots into multi user mode # [Unit] Before=network.target [Service] Type=oneshot ExecStart=/path/to/command ExecStart=/path/to/script arg1 arg2 RemainAfterExit=yes [Install] WantedBy=multi-user.target
For instance here is how we can install wireguard or openvpn iptables rules:
# /etc/systemd/system/wireguard-iptables.service [Unit] Before=network.target [Service] Type=oneshot ExecStart=/usr/sbin/iptables -t nat -A POSTROUTING -s 10.8.1.0/24 ! -d 10.8.1.0/24 -j SNAT --to 123.x.x.x ExecStart=/usr/sbin/iptables -I INPUT -p udp --dport 1194 -j ACCEPT ExecStart=/usr/sbin/iptables -I FORWARD -s 10.8.1.0/24 -j ACCEPT ExecStart=/usr/sbin/iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT ExecStop=/usr/sbin/iptables -t nat -D POSTROUTING -s 10.8.1.0/24 ! -d 10.8.1.0/24 -j SNAT --to 123.x.x.x ExecStop=/usr/sbin/iptables -D INPUT -p udp --dport 1194 -j ACCEPT ExecStop=/usr/sbin/iptables -D FORWARD -s 10.8.1.0/24 -j ACCEPT ExecStop=/usr/sbin/iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT RemainAfterExit=yes [Install] WantedBy=multi-user.target
And then:
$ sudo systemctl enable wireguard-iptables.service
$ sudo systemctl start wireguard-iptables.service
$ sudo systemctl stop wireguard-iptables.service
Conclusion
I hope you find this quick tutorial about enabling /etc/rc.local support useful for backward compatibility and ease of use purposes when using systemd. Make sure you read systemd documentation.
🐧 5 comments so far... add one ↓
Category | List of Unix and Linux commands |
---|---|
File Management | cat |
Firewall | Alpine Awall • CentOS 8 • OpenSUSE • RHEL 8 • Ubuntu 16.04 • Ubuntu 18.04 • Ubuntu 20.04 |
Network Utilities | dig • host • ip • nmap |
OpenVPN | CentOS 7 • CentOS 8 • Debian 10 • Debian 8/9 • Ubuntu 18.04 • Ubuntu 20.04 |
Package Manager | apk • apt |
Processes Management | bg • chroot • cron • disown • fg • jobs • killall • kill • pidof • pstree • pwdx • time |
Searching | grep • whereis • which |
User Information | groups • id • lastcomm • last • lid/libuser-lid • logname • members • users • whoami • who • w |
WireGuard VPN | Alpine • CentOS 8 • Debian 10 • Firewall • Ubuntu 20.04 |
I hate systemd. Old good Debian 8.x was nice. Debian 10 and systemd. I may switch to FreeBSD.
At least on my RHEL/CentOS 8 and Fedora Linux file is /etc/rc.d/rc.local but it is symlinked too:
ls -l /etc/{,rc.d}/rc.local
I saw:
May be update page?
I added info. HTH
Perhaps this only exists in Debian/Ubuntu based distros, couldn’t find it anywhere in Arch/Manjaro system.
Here is how you enable rc.local on Arch Linux:
sudo vim /etc/systemd/system/rc-local.service
Add:
Enable it:
sudo systemctl enable rc-local.service
Create /etc/rc.local
sudo touch /etc/rc.local
sudo chmod +x /etc/rc.local
sudo vim /etc/rc.local
Start it:
sudo systemctl start rc-local.service
sudo systemctl status rc-local.service