Systemd is Here!
With the arrival of systemd in the buntu universe the old way of setting up startup and shutdown scripts is outdated. In theory you can use the old SysVinit approach but my shutdown scripts were not executing so I decided to bite the bullet and learn how to do it with Systemd.
You'd think there would be a blog post saying, "do a, b, c and you're good" but I couldn't find one so after a bit of research here it is. My main sources of information were an excellent article at CertDepot that explains the basics of systemd commands and file structure, and a discussion on stackexchange about running a script at shutdown.
Background.
In systemd you create services to let systemd know what you want it to do. The best place to store these is in the directory /etc/systemd/system.
You still need scripts that will perform the tasks you plan to run at startup and shutdown. I created hidden scripts in my home directory.
How to do it.
First create the scripts you want to run at startup and/or shutdown. I created .scopening_atstart and .scfullcopy_atend.
Then make sure that they are both executable by right clicking the file, selecting properties and making sure that, under permissions, you have ticked Allow executing file as a program. You could also open a terminal and at the command line type chmod +x filename.
The two files I created populate and depopulate a ramdisk. They also create a file in my home directory to prove that the service is working. They were of the form:
Then I opened /etc/systemd/system and created a file startup.service and a file save-ramdisk.service. Obviously you can choose your own names and generic names could have included a startup file called johns_start.service and a shutdown file called johns_shutdown.service. Just don't pick existing service names. Their content was:
and
You can use the same service files, substituting the full path of your executable script for mine.
Finally for each one execute the command systemctl enable your_files_name (but without the suffix service) so my first one was systemctl enable startup
My shutdown script didn't work on my first exit possibly because I hadn't started the service before shutting down. On the second shutdown, and then a reboot, it worked perfectly. Additional useful commands include:
systemctl is-enabled startup
systemctl is-active startup
systemctl restart startup
More information can be found at the first reference above.
Power User Version
So, how about a master of the command line?
I will assume that you use sudo and your choice of editor, and that you are in your home directory.
You may execute commands directly from the systemd service files or call executable shell scripts. Don Crissti discusses some startup commands at StackExchange.
Shell Scripts. The file below assumes that you have created two executable shell scripts named .startup_commands and .shutdown_commands in your user's home directory and that your name is john (please change the user name). A simple version of the startup script, that creates a file in your home directory, would be:
#!/bin/sh
#
date +%D' '%T > /home/john/startup_time
After creation you would have made the file executable:
chmod +x .startup_commands
Service Files.
# Create a file with the suffix service in the /etc/systemd/system directory
vim /etc/systemd/system/start_and_stop.service
# Copy the following content into the file, here called start_and_stop.service
# This version uses one file for startup & shutdown. Separate files are show above.
[Unit]
Description=Run Scripts at Start and Stop
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/home/john/.startup_commands
ExecStop=/home/john/.shutdown_commands
[Install]
WantedBy=multi-user.target
Commands
Enable the Service
# enable
systemctl enable start_and_stop
That's it. After the first reboot, systemd will run .startup_commands as part of the multi-user start up process and .shutdown_commands when you shut down or reboot your system.
More Service File Options - Changing Targets
Above we have a service file that executes when multi-user starts up, one that executes when it shuts down, and a third that executes on it's start up and shutdown. It is also possible to achieve finer distinctions.
The files above all use the open or close of the multi-user environment to initiate running the scripts. The file below uses the beginning of four potential shutdown processes to initiate its scripts.
This was discussed in the second answer of this Stack Exchange post but I was unable to get it to run without adding the WantedBy line.
Again, edit the script in /etc/systemd/service/ and enable it using systemctl enable your_file_name. When I changed the targets I used the systemclt disable file_name command and then re-enabled it which symlinked it to the target directories.
[Unit]
Description=Do something required
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target
# This works because it is installed in the target and will be
# executed before the target state is entered
# Also consider kexec.target
[Service]
Type=oneshot
ExecStart=/home/john/.my_script
[Install]
WantedBy=halt.target reboot.target shutdown.target
Thank you so much for this post. I had looked at several other posts but I could not understand what was going on. Your Power User Version example is what did it for me.
ReplyDeleteI use an old laptop connected to my local network via Wi-Fi. My problem was that during the laptop shutdown the Wi-Fi link would close before the mounted shares were disconnected. So during shutdown or reboot the process would hang trying to un-mount the shares.
#!/bin/bash
#File Name: "/home/patrick/shutdown_commands"
clear
echo "This will unmount all shares on this laptop"
echo ""
sudo umount /nfs/share
sudo umount /nfs/DATA
sudo umount /nfs/1TB-Audio
sudo umount /nfs/home
#
rm /home/patrick/shutdown_time
date +%D' '%T > /home/patrick/shutdown_time
#
echo ""
echo "All local nfs shares should be unmounted."
echo "It is now safe to do a SHUTDOWN or RESET"
echo ""
This script worked perfectly so that I no longer have to manually un-mount my shares before shutdown or reboot.
Thank you for this post! Patrick
Thank you for your post. A variant of your last unit file -- the one under 'More Service File Options - Changing Targets' -- is the only unit file that will allow a Bash script for backing-up to run to completion at shutdown. All other unit file solutions purporting to run a Bash script at shutdown do indeed run the script when shutdown is initiated, but shutdown the PC before the script has completed the lengthy back-up process.
ReplyDeleteThanks for this clear explanation of building a systemd service. Goes along way in understand systemd for us older linux guys
ReplyDelete