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
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
Does not run at shutdown, it runs at boot??
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 🙏
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.
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.
This scrips works in debian 11, but only executes at powerdown and not reboot. You could change as follows:
Nice! Work very well for me.
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.
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
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.
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 jobsAlso 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.
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?
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.
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 😥
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
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