Execute a script upon logout/reboot/shutdown in Ubuntu

50,725

Solution 1

How to do it with systemd

If you find this thread after June 2016, Ubuntu and its derivatives including Mint will be using systemd to control system initialization and shutdown. I had problems with the old approach so researched the systemd way.

With systemd you create one or two files to call your scripts using the templates below, and execute a command. 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 showed some alternatives at Stack Exchange.

svim /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 an answer at Unix & Linux by @Matthias 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 systemclt 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

Debugging

I recently (2020) did a little distro hopping, first to KDE Neon where I discovered that although KDE is light on memory, its cpu usage was considerably higher than mint, and then to Fedora 33 XFCE.

With the second, neither of these scripts worked. So I followed the hints and used systemctl status and journalctl -xe to find the issues. It turned out that something didn't have permission to run the scripts in my home directory. I experimented unsuccessfully until I changed the invocation to:

ExecStart=/usr/bin/bash /home/john/.scopening_atstart

This may help someone; but be aware that your system may be using /bin/bash so check your file names and paths.

Solution 2

To execute a script upon logout:

  1. Add the following line in /etc/lightdm/lightdm.conf file:

    session-cleanup-script=/path/to/script
    
  2. You have to restart LightDM in order for this change to take effect. To do this go in TTY1 using Ctrl+Alt+F1, login with your username and password and run the following command:

    sudo service lightdm restart
    
  • Note: use Ctrl+Alt+F7 to switch to the graphical session.

To execute a script upon reboot:

  1. Put your script in /etc/rc0.d.

  2. Make it executable:

    sudo chmod +x K99_script
    
  • Notes:
    • The scripts in this directory are executed in alphabetical order.
    • The name of your script must begin with K99 to run at the right time.

To execute a script at shutdown:

  1. Put your script in /etc/rc6.d.

  2. Make it executable:

    sudo chmod +x K99_script
    
  • Notes:
    • The scripts in this directory are executed in alphabetical order.
    • The name of your script must begin with K99 to run at the right time.

Sources:

Share:
50,725

Related videos on Youtube

DirtyDenimDan
Author by

DirtyDenimDan

Updated on September 18, 2022

Comments

  • DirtyDenimDan
    DirtyDenimDan over 1 year

    I'd like to run a .sh file using bash on logout and shutdown of Ubuntu. I have searched up and down the web and have found only fixes for KDE and GNOME. The script is simple, I just need to know if I can add the line of code to the "logoff/shutdown" file or if I need to reference it in another script.

    • Admin
      Admin over 6 years
      Please consider accepting the updated answer (using systemd) so people would see it on top.
    • Admin
      Admin over 4 years
      the updated answer misses the information about "running on logout", unfortunately
  • kiri
    kiri over 10 years
    It's conventional to name scripts starting with K for 'Kill' and S for 'Start'.
  • Urhixidur
    Urhixidur over 9 years
    What if the script needs sudo privileges? As far as I can tell, the /etc/rc6.d scripts are run as user, and cannot use gksudo.
  • tomasb
    tomasb over 9 years
    doesn't work for me with 14.04, is there any change or unspecified important fact?
  • terdon
    terdon almost 9 years
    This is very wrong: i) script names need to start with a K for runlevels 0, 1 and 6 and S for runlevels 2, 3, 4 and 5; ii) you don't need to call the script K99_foo, the number just determines the order the scripts are run in. You need to chose one that is larger than the others if you want it to be run last; iii) Runlevel 0 is not for reboot!; It's for shutdown. 6 is for reboot. iv) scripts have no business being in the /etc/rcN.d directories. They should instead be in /etc/init.d and linked to /etc/rcN.d.
  • Antonios Hadjigeorgalis
    Antonios Hadjigeorgalis over 7 years
    according to man systemd.unit user created files can be placed in $XDG_CONFIG_HOME/systemd/user and other local user locations
  • Anwar
    Anwar about 7 years
    Will it work with shutdown or with logout?
  • Anwar
    Anwar about 7 years
    What would be the approach If I'm not using lightdm?
  • John 9631
    John 9631 almost 7 years
    It does on my system Anwar (Mint 18). The trigger conditions are determined by the targets: shutdown.target reboot.target halt.target although I couldn't guarantee that the developers won't make minor changes to systemd behavior in future.
  • chrismarx
    chrismarx over 6 years
    Should this work to install a shutdown script on ec2? I see my installed service, everything looks good, but it's not running. I want it to run after a reboot is requested from the ec2 console.
  • chrismarx
    chrismarx over 6 years
    Also, I had to install systemd to follow these instructions for ubuntu 14.04 - sudo apt-get install systemd
  • Anwar
    Anwar about 6 years
    @John9631 Does this execute upon logout? If it's only run at shutdown, then it's useless for me. Anything to run upon logout with systemd
  • John 9631
    John 9631 about 6 years
    @Anwar, I think you're looking for something that doesn't exist. User login & out seems to be a user level process and varies depending on what you run. For more information: superuser.com/questions/970883/…
  • Anwar
    Anwar about 6 years
    @John9631 I'm not looking for login/logout history. I'm looking for ways to execute command at logout of a user session, which may or may not be in sync with shutdown. there were approaches to enable this in upstart (afaik), but I haven't found anything with systemd
  • John 9631
    John 9631 over 3 years
    @Anwar I suspect that the approach for logout would be to use the first style. So your script would be invoked on ExecStop and you could be more specific by linking it to graphical.target rather than multi-user.target.
  • simohe
    simohe about 3 years
    for autostart for various display managers: askubuntu.com/questions/48321/… (xxx.desktop in ~/.config/autostart/ should work for all)
  • Martin T.
    Martin T. almost 3 years
    There is /etc/sytemd/system/rc-local.service I just placed an additional ExecStop=<my script> here. (Took me hours to find a way to kill (old) rails apps running as daemons, not killed during normal reboot)
  • Henk Poley
    Henk Poley about 2 years
    Note that ExecStart/ExecStop can take command line variables.