We can easily enable rc.local shell scripting support in systemd when the Linux system boots. Traditionally, the /etc/rc.local shell script is used by Linux developers and sysadmin to invoke other scripts or commands after all services have loaded. Typically /etc/rc.local is called at the end when Linux init switches to multi-user runlevel. However, by default, /etc/rc.local support is disabled in systemd. In this article, we will show you how to enable and execute rc.local shell script at boot time using systemd on Linux.
Enabling rc.local shell script in systemd at boot of Linux system
Compatibility with /etc/rc.local is achieved through systemd using a special service called rc-local.service.
This module is automatically called in multi-user.target by systemd-rc-local-generator if /etc/rc.local is executable.
Executing rc.local shell script at boot time using systemd
Naturally, create or update / edit a file called /etc/rc.local using your favorite text editor.
I’m going to use the vim command:
$ sudo vim /etc/rc.local## RHEL/ CentOS /Fedora Linux отредактируйте файл /etc/rc.d/rc.local ##
$ sudo vim /etc/rc.d/rc.local
Add the required commands or call the 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.
? How to save file in Vi / Vim and exit
Make sure you set the executable permissions for the file with the chmod command:
$ sudo chmod -v +x /etc/rc.local
Setting up rc-local.service on Linux when systemd starts
All we need to do is enter the following systemctl command:
$ sudo systemctl enable rc-local.service
Reboot Linux:
$ sudo reboot
Check the status after reboot:
$ sudo systemctl status rc-local.service
Here’s what we see on the 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 itsecforu systemd[1]: Starting /etc/rc.local Compatibility Nov 04 13:29:54 itsecforu systemd[1]: Started /etc/rc.local Compatibility.
How to view service configuration
Open the terminal app and type:
$ sudo systemctl cat rc-local.service
We will see the 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 problems with /etc/rc.local when the script fails to load.
Linux runlevel information
When init was used by default, we had the following runlevels:
- S – boot Linux system
- 0 – turn off Linux
- 6 – Restart Linux
- 1 – Linux single user mode, used for Linux system emergency recovery
- 2-5 – Common multi-user system supporting both CLI and GUI and full network connectivity
Often times, Linux distributions and the Unix system have changed these runlevel values to suit their needs.
However, /etc/rc.local is called when the system enters multiuser mode through runlevels 2 through 5.
However, this default was removed when most Linux distributions switched to systemd.
Therefore, I wrote this quick guide for Linux developers and system administrators.
Creating your own service is easy with systemd on Linux
Instead of a shell script in /etc/rc.d/ or a call to /etc/rc.local, we’ll do it differently.
It only works on Linux, not other Unix flavors. Then 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 example, here’s how we can set 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 guide to enabling /etc/rc.local support useful for backward compatibility and ease of use with systemd.