You are not logged in.

#1 2020-03-12 16:13:06

reddhawk
Member
Registered: 2012-07-02
Posts: 28

Execute a script before poweroff/reboot/halt

Hello everybody. I have a problem that might be easy to solve to some of you. My goal is to shut down gracefully my system, taking down all the virtual machines running before actually shut the host system down.

At the moment, to do so I created these aliases in my .zshrc:

alias sudocheck="/bin/bash /home/damiano/.script/sudocheck"
alias sudo="sudocheck "

That point to this script here:

#!/bin/bash

# This script checks for what is being passed to sudo.
# If the command passed is poweroff or reboot, it
# launches a custom script instead, that also looks
# fur currently running virtual machines and shuts them.

sudocheck() {
    if [ $1 == "poweroff" ] || [ $1 == "reboot" ]; then
        eval "sudo /home/damiano/.script/graceful $@"
    else
        eval "sudo $@"
    fi
}
sudocheck $@

That goes to this one if a sudo shutdown or a sudo reboot is being launched by me:

#!/bin/bash
i=0
e=0
## if virsh finds VMs running
virsh -c qemu:///system list | awk '{ print $3}' | \
if grep running > /dev/null ; then
    virsh -c qemu:///system list --all | grep running | awk '{print "-c qemu:///system shutdown "$2}' | \
## shuts them dow gracefully
    xargs -L1 virsh
## wait 30 seconds for them to go down
    until (( i >= 30 || e == 1 )) ; do
## check every second for their status
        virsh -c qemu:///system list --all | awk '{ print $3}' | \
        if grep -E '(running|shutdown)' > /dev/null ; then
## keep waiting if still running
            if (( i <= 30 )) ; then
                sleep 1 && let i++ && echo $i
            else
                e=1 && notify-send 'Shutdown has been canceled' 'Please check the status of your virtual machines: seems like even though a stop signal has been sent, some are still running.' --urgency=critical
            fi
        else
## if no machine is running anymore, original power command can be executed
            e=1 && eval $@
        fi
    done
fi

Now, despite it works, I would like to find something more elegant. First of all, this works only if I launch the command from a zsh shell. Second I don't like the idea that for every sudo I launch I have a custom script in the middle.

For example it would be so much better to put this more down in the line, so that even if I shut down the pc through a desktop environment GUI I still get that check done.

Please advice and help me, gurus! big_smile

Last edited by reddhawk (2020-03-13 12:30:56)

Offline

#2 2020-03-12 17:15:11

Docbroke
Member
From: India
Registered: 2015-06-13
Posts: 1,372

Re: Execute a script before poweroff/reboot/halt

alias poweroff="<yourscript> && sudo /usr/bin/poweroff"

This will save you from running middle script for every sudo run.


Arch is home!
cwm rofi weaver clifm vis lizzy pass terminator
https://github.com/Docbroke

Offline

#3 2020-03-12 18:07:46

DAMO238
Member
Registered: 2020-02-25
Posts: 45

Re: Execute a script before poweroff/reboot/halt

Another way of doing it more generically could be to create a systemd service and let systemd take care of it for you. That way, it will happen no matter how you poweroff!

Offline

#4 2020-03-13 02:42:07

reddhawk
Member
Registered: 2012-07-02
Posts: 28

Re: Execute a script before poweroff/reboot/halt

Docbroke wrote:

alias poweroff="<yourscript> && sudo /usr/bin/poweroff"

This will save you from running middle script for every sudo run.

Thanks for the idea doc, I know. initially I didn't make an alias on poweroff to keep the command with sudo as I'm used to do. But yeah, guess I'd switch to this if I don't find anything better. Thanks for posting!

DAMO238 wrote:

Another way of doing it more generically could be to create a systemd service and let systemd take care of it for you. That way, it will happen no matter how you poweroff!

This sounds reeeeally interesting big_smile What do you mean exactly? For example gnome uses this command to shutdown:

dbus-send --system --print-reply --dest=org.freedesktop.login1 /org/freedesktop/login1 "org.freedesktop.login1.Manager.PowerOff" boolean:true

What you had in mind would take care of something like this too?

Offline

#5 2020-03-13 08:57:23

glitsj16
Member
Registered: 2015-04-26
Posts: 108

Re: Execute a script before poweroff/reboot/halt

I'm not DAMO238 but I would recommend the same. If you can make a systemd unit to start your virtual machines, the same systemd unit will take care of stopping them before poweroff/reboot/halt. Can you elaborate on how you start these virtual machines currently?

Offline

#6 2020-03-13 12:22:22

reddhawk
Member
Registered: 2012-07-02
Posts: 28

Re: Execute a script before poweroff/reboot/halt

glitsj16 wrote:

I'm not DAMO238 but I would recommend the same. If you can make a systemd unit to start your virtual machines, the same systemd unit will take care of stopping them before poweroff/reboot/halt. Can you elaborate on how you start these virtual machines currently?

At the moment I just use the "Start virtual machine on host boot up" flag in the "Boot Options" tab of virt-manager. But yeah, sure I can do a systemd unit like the following for example:

bootvm@.service

[Unit]
Description=This service manages the execution of the %i virtual machine
Documentation=https://libvirt.org/manpages/virsh.html

[Service]
ExecStartPre=virsh -c qemu:///system
ExecStart=virsh start %i
ExecStop=virsh -c qemu:///system
ExecStop=virsh shutdown %i 
TimeoutStopSec=30
KillMode=none

[Install]
WantedBy=multi-user.target

But this still doesn't do what I want. I mean, what I want to reproduce is:

- A shutdown / poweroff / reboot / halt signal is sent to the system
- No action from the host, other then trying to shut down the virtual machines gracefully
- If the VMs are shut down gracefully after X seconds, proceeds with shutting down the host system too.
- If not, execute a different command

Any idea how to implement it somehow or in any of the above code?

Last edited by reddhawk (2020-03-15 03:39:59)

Offline

Board footer

Powered by FluxBB