How to run script with systemd right before shutdown in Linux


systemd, How To, Linux, Tips and Tricks

In this article I will share example and sample systemd unit service file to run script with systemd right before shutdown in CentOS/RHEL 7/8 Linux. Using this systemd unit file you can run either some command or script as a last service before shutdown in Linux.

Now ideally any systemd service gets called via ExecStop at shutdown stage and with ExecStart at boot up stage. But here our requirement is little different, we wish to run script with systemd right before shutdown stage. Now this can be a normal shutdown or reboot.

 

Step 1: Overview on systemd

If you are a beginner to systemd then I would recommend you to also read Overview on systemd and how it is different from legacy SysV scripts before starting with this tutorial.

 

Step 2: Create Sample Script

Now to run script with systemd right before shutdown we need a script or command. For the sake of this article I will use a script from another article of mine /tmp/startup_script.sh. This script will run for 3 minutes in a loop to check and make sure the script is not killed due to shutdown. We want the script to run and halt the shutdown until completely executed

# cat /tmp/startup_script.sh
#!/bin/bash
z=0
for i in {1..3}; do
    sleep 1m
    ((z++))
	echo ""
done

Provide executable permission to the script

chmod u+x /tmp/startup_script.sh

 

Step 3: Create unit file to run script with systemd right before shutdown

Now as highlighted under step 1, I have already written another article with the steps to create a new systemd unit file. Here we will name our systemd unit file as run-before-shutdown.service under /etc/systemd/system. Below is the content of run-before-login-prompt.service

[root@centos-8 ~]# cat /etc/systemd/system/run-before-shutdown.service
[Unit]
Description=Run my custom task at shutdown
DefaultDependencies=no
Before=shutdown.target

[Service]
Type=oneshot
ExecStart=/tmp/startup_script.sh
TimeoutStartSec=0

[Install]
WantedBy=shutdown.target

Here the main task is done by Before=shutdown.target and TimeoutStartSec=0. For more details check man page of systemd.service

TimeoutStartSec=   	When a service doesn't signal start-up completion within TimeoutStartSec, systemd considers the service failed; 
			for long-running shell scripts it is essential to modify TimeoutStartSec or disable the timeout logic altogether 
			as above, with TimeoutStartSec=0. See man systemd.service for more details.

Before=   		If the script needs to be run before other services--for example, prior to starting sshd or console/graphical 
			logins ensure there is a Before=XYZ.service in the [Unit] section and a corresponding RequiredBy=XYZ.service 
			in the [Install] section.

Refresh the systemd configuration files

[root@centos-8 ~]# systemctl daemon-reload

Enable the script to automatically start at next boot

[root@centos-8 ~]# systemctl enable run-before-shutdown.service
Created symlink /etc/systemd/system/shutdown.target.wants/run-before-shutdown.service → /etc/systemd/system/run-before-shutdown.service.

 

Step 3: Verify the systemd unit file configuration

Now since we are done with the setting up of systemd. Let us verify our configuration.

reboot
How to run script with systemd right before shutdown in Linux

We are using Oracle VirtualBox so post reboot we will check the console of our Virtual Machine

As expected we see that our systemd service is running and not allowing shutdown to complete.

Lastly I hope the steps from the article to run script with systemd right before shutdown on CentOS/RHEL 7/8 Linux was helpful. So, let me know your suggestions and feedback using the comment section.

Related Searches: run script with systemd right before shutdown. how to execute shell script before shutdown. run script before shutdown linux. run script on shutdown linux

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

15 thoughts on “How to run script with systemd right before shutdown in Linux”

  1. Been banging my head against the wall for about six hours now trying to get a zpool export service to run at shutdown and not killed/skipped (over 300+ google searches probably). This was the only, and I mean only one that worked. Thank you so much for this 🙏

    Reply
  2. I wrote a new custom script to take down the shutdown time, but the service was never triggerred. I am wondering if the storage part had been umounted at that stage.

    Reply
    • You can modify your script to check the current status of connected disks when the script is getting executed. In systemd everything happens in parallel unless we have defined explicit dependency so this can become tricky sometimes to debug.

      Reply
  3. This scrips works in debian 11, but only executes at powerdown and not reboot. You could change as follows:

    [Unit]
    Description=Run my custom task at shutdown
    DefaultDependencies=no
    Before=shutdown.target reboot.target
    
    [Service]
    Type=oneshot
    ExecStart=/tmp/startup_script.sh
    TimeoutStartSec=0
    
    [Install]
    WantedBy=shutdown.target reboot.target
    Reply
  4. [Unit]
    Description=Stop CDH cluster before shutdown
    DefaultDependencies=no
    Before=shutdown.target network.target poweroff.target halt.target

    [Service]
    Type=oneshot
    ExecStart=/usr/bin/python2.7 /usr/bin/clusterstop.py
    TimeoutStartSec=0

    [Install]
    WantedBy=shutdown.target

    I set my halt time service like this. It is not getting triggered at all the the time of Shutdown or Reboot. Works while invoking the service manually.
    What can be the configuration issue here? On reboot I am seeing python error messages under service status, I am not sure python is getting env at the time of service invoke.

    Reply
    • Hi Jinesh,

      I believe your script is getting called, just that the execution fails which is why you are seeing python error messages. If it was environment variable problem then your script wouldn’t get called in the first place.
      There may be some dependency for the script? Does it require file system to be accessible or network as in such case we have to modify the systemd unit file accordingly. In my case here the script is running for sure but in the background other services may be going down in parallel so we need add dependency

      Reply
  5. Hey, sorry for the late reply.
    So here is somethings i tried:
    My script will shutdown tomcat, creates a empty file on a shared efs and make a DB change
    1. If i use LIFECYCLE hooks the same script makes does all the three things as mentioned above.
    2. If i use your solution it did not do anything.
    Could you please suggest? I mean strange it did not run for me.
    I am assuming that Shutdown occurs every-time we Terminate or stop EC2 instance.

    Reply
    • Hello Mohit, I am not very familiar with EC2 instances. I have verified this solution on Physical HW and Virtual Machines where it seemed to work as expected. In your case first we need to understand whether the script gets called in the first place
      You can add systemctl list-jobs >> /tmp/file to your script to check list of active jobs
      Also modify Before=shutdown.target poweroff.target halt.target
      It can be the way the node goes down. Try a normal shutdown and observe the behaviour.
      I don’t have any such setup or else I would have tried to check this locally so I am afraid I can only give hints.

      Reply
  6. It did not run for me, i am using Amazon2 AMI i did exactly what you did just change in the script, i created a shell script in which i am stopping tomcat and echoing some text in a log file. That log file is on shared location i.e. on efs, and when i try to check efs from other ec2 nodes i can not see any log file created. That means your thing did not work for me.

    Could you please again check this?

    Reply
    • Hi Mohit,

      Did you checked with local storage? Is it possible your shared storage is not accessible at the time the script was writing to log file? You should also add some commands to check the currently mounted file system at the time the script is getting called.

      Reply
      • Hey could you please help me in checking that?
        Actually when i run the lifecycle hooks the same script runs and it creates a file in efs. I have 4 ec2 instances and i only terminate on and efs if shard between these 4. I could check on other ec2.

        But when i wanted to use your script it didnt even create.
        I also edited that script to make some DB changes like updating a column value so this made me confident enough that your script didn’t update it but lifecycle hooks did.

        I don’t want to use lifecycle hooks that is why i read your blog and its good. But not sire why its not making any difference to my requirement 😥

        Reply
  7. It doesn’t work correctly.
    1) Script runs at shutdown but has no access to internet, so there no way to perform a back-up to cloud storage.
    2) Script also (!) starts at boot-up and during boot-up it has internet access and performs a back-up.
    Ubuntu 19.10 & systemd 242

    Reply
    • Hello Yevhenii,

      Thanks for your feedback.
      1. If you also need active internet then you should use
      Before= shutdown.target network.target
      under [Unit] section
      2. That should not be the case as we are explicitly defining to start before shutdown.target. Can you share me the logs from /var/log/message for further debugging

      Reply

Leave a Comment