5

I’m trying to run a script at shutdown and reboot without success. I have a script to run as root at startup and it works just fine: stored the script in /etc/init.d, created a link to it in /etc/rc2.d starting with S99 and make it executable. After some research I did the same with the shutdown script creating the links in /etc/rc0.d and /etc/rc6.d, making it executable and starting links name with ‘K99myscript’ but the script doesn’t run. I’ve tried changing the links name to ‘K00myscript’ to run before the others, changing from sh to bash (#! /bin/sh to #! /bin/bash) but nothing seems to help. I’m running Xubunto and using ‘systemctl poweroff’ to shutdown and ‘systemctl reboot’ to restart. Is this an obsolete method?

I’ve also tried to create a .service in /etc/systemd/system as suggested:

[Unit]
Description=Pre-Shutdown Processes
DefaultDependencies=no
Before=shutdown.target reboot.target halt.target kexec.target

[Service]
Type=oneshot
User=root
Group=root
ExecStart=/etc/init.d/myscript

[Install]
WantedBy=shutdown.target reboot.target halt.target kexec.target

Both with and without User/Group fields but it didn't worked...

4
  • Why is it important to run a script at shutdown? Would it be enough to run all scripts at boot (cold boot as well as reboot)? In that case you could use @reboot in crontab.
    – sudodus
    Aug 9, 2021 at 9:08
  • Does this answer your question? How to run a command BEFORE shutdown on Ubuntu 21.04
    – FedKad
    Aug 9, 2021 at 12:40
  • In a user level it would be easy to perform some tasks at shutdown, reboot, logout… XFCE has a nice GUI for that with just .desktop files. But I need to perform them as root. The systemd service method didn’t work even specifying the User and Group as root. But I’ve found some nice clues here: [18.04 - insserv missing on Ubuntu 18 ](askubuntu.com/questions/1048330/insserv-missing-on-ubuntu-18) Although I have to study a little more about it and understand how the LSB header should be configured. As far as I know the rc*.d method is getting obsolete. Aug 10, 2021 at 6:02
  • Unless we are talking about security or privacy issues, I think it should be good enough to use @reboot in crontab. You run it with root permissions via sudo crontab -e. Otherwise I suggest a workaround: make a 'custom shutdown', a desktop file that executes a shellscript, that runs your special tasks, and then performs shutdown.
    – sudodus
    Aug 10, 2021 at 9:24

1 Answer 1

6

[SOLVED] Being a bit stubborn is, sometimes, the good path for a solution. Nevertheless, thanks for your contributions. After some research based on the link of my previous comment (Sebastian Stark's answer), I ended up with this script (let’s call it ‘myoffscript’) in my /etc/init.d folder:

#!/bin/sh
### BEGIN INIT INFO
# Required-Start:    $local_fs
# Required-Stop:     $local_fs
# Provides:          Shutdown or Reboot Exec
# Default-Start:     4
# Default-Stop:      0 6
# Description:       Shutdown or Reboot
### END INIT INFO

case "$1" in
    stop)
             echo $(date) >> /ZZZdate # REPLACE PREVIOUS EXAMPLE: EXECUTE SHUTDOWN/REBOOT COMMANDS HERE
         ;;
esac

exit 0

Regarding the above script the most important to highlight is:

1 - The LSB (Linux Standard Base) header – ‘Default-Start’ and ‘Default-Stop’ run levels must be both present, corresponding ‘0’ to shutdown (rc0.d) and ‘6’ to reboot (rc6.d). As my script is only for shutdown and reboot and the ‘Default-Start’ must be specified, I’ve chosen ‘4’ (rc4.d) witch is not used/user-definable. But it should be run level ‘2’ (rc2.d) if starting something at boot time is needed (like a service, daemon,…)

2 - The case statement - As the scrip is executed by systemd as a service with the arguments ‘start’ or ‘stop’ according to the ‘Default-Start’ and ‘Default-Stop’ from the LSB header, all the commands must be inside of the case statement. (Commands before the case statement were ignored in my tests.) Corresponding to run levels ‘0’ and ‘6’, my case statement has only the stop) option, but if running at boot time is needed, a start) option should be included (and run level ‘2’ must be specified in the LSB header ‘Default-Start’).

Now, let’s make it work. First make the script /etc/init.d/myoffscript executable. Then, we have two options - with a command or manually.

With a command:

# systemctl enable myoffscript

or

# /lib/systemd/systemd-sysv-install enable myoffscript

The relative symbolic links will be automatically created in the corresponding rc*.d folders (S01myoffscript in rc4.d and K01myoffscript in rc0.d and rc6.d according the to the script above) The commands wil only work if the links were not created before. Otherwise errors will be reported.

Manually: From each rc*.d folder create the symbolic link

# cd /etc/rc4.d
# ln -s ../init.d/myoffscript S01myoffscript
# cd /etc/rc0.d
# ln -s ../init.d/myoffscript K01myoffscript
# cd /etc/rc6.d
# ln -s ../init.d/myoffscript K01myoffscript

Note: if run level ‘2’ was specified in ‘Default-Start’, the first link should be created in /etc/rc2.d and so on... Restart the system and everything should work.

This is the only way that I’ve found to run a script as root at both shutdown and reboot with Ubuntu 20.04

Note: Despite the /etc/int.d and /etc/rc2.d links method is still working to run scripts/commands at boot time, as mentioned in my previous comment link, a long-term approach would be to convert init scripts to systemd service units, so the LBS header with the case statement method described above may be useful for startup scripts/commands in a few time.

5
  • Thanks for sharing this solution :-)
    – sudodus
    Aug 11, 2021 at 7:18
  • Does this work with systemd systems or just system V/ SysVinit?
    – acampana
    Jun 20, 2022 at 11:02
  • As far as I know, since version 15.04 Ubuntu is a systemd system. So, it should work. Jun 22, 2022 at 0:04
  • 1
    This isn't a good solution - whatever you think about systemd, it's here to stay, and SysV scripts are obsolete and will stop being supported. LSB is also dead. Your service file is the right way to go, but it needs cleaning up. You need ExecStop, not ExecStart, WantedBy should be multi-user.target, and get rid of DefaultDependencies, Before, User, and Group.
    – EML
    Sep 24, 2023 at 12:48
  • Thank you EML for your review. It's just the way I found it to work in the explicit context and I explained what I did to make it understandable. I'm always learning from criticism from those who know more than me. Could you please post your corrected version of the service here? Thanks. Oct 27, 2023 at 1:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .