I want to execute a simple command just before the computer shuts down (timing is not essential).
For startup, I can use /etc/rc.local; is there something similar for shutdown?
Note that I would still like to use the integrated shutdown button from menu; i.e. I don’t want to use a custom script every time I shutdown via terminal – it needs to be automatic.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Linux Mint is based on Ubuntu, so I’m guesing the runlevel system is probably the same. On Ubuntu, scripts for the different runlevels are executed according to their presence in the /etc/rc[0-6].d directories. Runlevel 0 corresponds to shutdown, and 6 to reboot.
Typically the script itself is stored in /etc/init.d, and then symlinks are placed in the directories corresponding to the runlevels you require.
So in your case, write your script, store it in /etc/init.d/, then create a symlink in each of /etc/rc0.d and /etc/rc6.d (if you want both) pointing to your script.
The scripts in each runlevel directory will be executed in asciibetical order, so if the order within the runlevel matters to you, choose the name of your symlink accordingly.
Method 2
Now that the Ubuntu variants and Mint have moved to systemd I found my old solutions based on the above to be less satisfactory. I searched around the web to find out how to do it with systemd and ended up combining others’ wisdom and documenting it as a blog post at blogspot.com.au containing the following tutorial.
With systemd you create one or two files to call your scripts using the templates below, and execute a couple of commands. Simple.
GUI Version
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.
The two files I created populate and save the contents of a ramdisk. They also create a file in my home directory to prove that the service is working. They were of the form:
#!/bin/sh cp -pru /home/john/zRamdisk/subdirectory1/* /home/john/.wine/drive_c/subdirectory1/ rm /home/john/stop_time date +%D' '%T > /home/john/stop_time
Then I opened my file manager as root, 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.
[Unit] Description=Startup Applications [Service] Type=oneshot RemainAfterExit=false ExecStart=/home/john/.scopening_atstart [Install] WantedBy=multi-user.target
and
[Unit] Description=Save Ramdisk to Wine drive C [Service] Type=oneshot RemainAfterExit=true ExecStart=/bin/true ExecStop=/home/john/.scfullcopy_atend [Install] WantedBy=multi-user.target
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
Reboot the computer once to start the services. The start service will be executed whenever systemd enters the multi-user target and the stop service when it exits the multi-user target. Alternative service files with different activation conditions will be described below.
CLI (Command Line) Version
This description assumes that you operate from your home directory rather than /home/john, use sudo as needed, and your choice of editor where I write vim or svim.
Create startup and shutdown shell scripts with the first line #!/bin/sh and make them executable using chmod +x my_new_filename.
Create two files as above, or in this example, one file to handle startup and shutdown tasks. I will execute scripts in my home directory but @don_crissti shows some alternatives at Stack Exchange.
vim /etc/systemd/system/start_and_stop.service
and copy in the file content:
[Unit] Description=Run Scripts at Start and Stop [Service] Type=oneshot RemainAfterExit=true ExecStart=/home/john/.startup_commands #your paths and filenames ExecStop=/home/john/.shutdown_commands [Install] WantedBy=multi-user.target
Then Enable the Service with the command:
systemctl enable start_and_stop
and reboot your system after which the services will be active. The commands systemctl is-enabled start_and_stop and systemctl is-active start_and_stop can be used in monitoring your new services.
Changing the Trigger Conditions for Shutdown
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. Adding or removing the targets on the Before line + the WantedBy line will let you make finer distinctions:
This file was proposed in the second answer of this post but I was unable to get it to run until I added an Install section.
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 systemctl disable file_name command and then re-enabled it which symlinked it to the target directories. Reboot and the service will be operating.
[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 #your path and filename [Install] WantedBy=halt.target reboot.target shutdown.target
Method 3
You need to use rc.shutdown the shutdown script for the Linux Kernel.
Quoting the OpenBSD man page:
When the system is shut down using the reboot(8) or halt(8) commands,
or
when init(8) is signalled to do so, or when a keyboard-requested halt is
issued (if the architecture supports it), rc(8) is invoked with the
argument “shutdown”.
So, you simply open your rc.shutdown and add whatever shell commands you want to execute to it.
UPDATE: Since Linux Mint is based on Ubuntu, which has a different startup/shutdown procedure, here is the procedure relevant to you:
Write the shell script you wish to execute and copy it to the relevant directory in your /etc/rc*.d/. The * corresponds to the runlevel at which you want the script to execute.
Ubuntu follows the Debian runlevel numbering, so you have runlevel 0 for halt and runlevel 6 for reboot.
Method 4
For SysV dependency based init systems used in Debian Wheezy, Devuan and its derivates and maybe others, you can mimic the behavior of rc.shutdown analogue to rc.local like the following:
Add your commands to the following skeleton of /etc/rc.shutdown:
#!/bin/sh -e # # rc.shutdown # # <add your commands here, before exit 0> exit 0
Save the script and make the file executable with chmod a+x /etc/rc.shutdown.
Then, add a new script /etc/init.d/rc.shutdown to your system with the following content:
#! /bin/sh
### BEGIN INIT INFO
# Provides: rc.shutdown
# Required-Start:
# Required-Stop:
# X-Stop-After: umountroot
# Default-Start:
# Default-Stop: 0 6
# Short-Description: Run /etc/rc.shutdown if it exist
### END INIT INFO
PATH=/sbin:/usr/sbin:/bin:/usr/bin
. /lib/init/vars.sh
. /lib/lsb/init-functions
do_stop() {
if [ -x /etc/rc.shutdown ]; then
[ "$VERBOSE" != no ] && log_begin_msg "Running local shutdown scripts (/etc/rc.shutdown)"
/etc/rc.shutdown
ES=$?
[ "$VERBOSE" != no ] && log_end_msg $ES
return $ES
fi
}
case "$1" in
start)
# No-op
;;
restart|reload|force-reload)
echo "Error: argument '$1' not supported" >&2
exit 3
;;
stop|status)
do_stop
exit 0
;;
*)
echo "Usage: $0 start|stop" >&2
exit 3
;;
esac
Also make this script executable.
Create the symlinks in /etc/rc[06].d:
cd /etc/rc0.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown
and
cd /etc/rc6.d ; ln -s ../init.d/rc.shutdown K01rc.shutdown
Use insserv to correct the symlinks and to create the necessary .depend.boot, .depend.start, and .depend.stop files:
insserv -v
You need to be root or use sudo for all commands mentioned above.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0