Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I'm trying to do some stuff at logout, and the task can take up to 5 minutes to complete.

If the user chooses Power off or Reboot directly, the script is killed before completion. If the user just chooses Log out, the script is executed with no problems.

I've tried using pam_exec and lightdm property session-cleanup-script to point to my script, but it's the same in both cases.

The script used to do the testing is this one:

#!/bin/bash
touch /tmpfile
for p in $(seq 0 300) ; do
    sleep 1
    echo $p >> /tmpfile
done

When logging out, all the 300 numbers are written to the file. When shutting down or rebooting directly from within the user session, only 2 or 3 numbers are written, so the script is being killed.

How is handled the shutdown by lightdm? How can I ensure my script is not being killed?

If you propose an alternative approach, please take care that I need to know what user is being logged out and be able to run a script as that user. I also need to notify the user about what's happening, so better stay on X if possible.

share|improve this question
add comment

3 Answers

In Ubuntu, scripts for different runlevels are executed according to their presence in the /etc/rc[0-6].d directories. Runlevel 0 corresponds to shutdown, and 6 to reboot.

Typically the script is stored in /etc/init.d, and then symlinks are placed in the directories corresponding to the runlevels you require.

So in your case, write your script, store it in /etc/init.d/, then create a symlink in each of /etc/rc0.d and /etc/rc6.d (if you want both) pointing to your script.

Create a symlink like: /etc/rc0.d/K01myscipt -> /etc/init.d/myscript

The scripts in each runlevel directory will be executed in ASCIIbetical order, so if the order within the runlevel matters to you, choose the name of your symlink accordingly.

Hope that solves it. Don't forget to make it executable (sudo chmod +x myscript). Also, I'm not sure, but maybe you'll have to cancel shutdown at the beginning of the script - shutdown -c now and issue it again at the end - shutdown -h now.

Now to know, who issued the shutdown command :
1) Either, Well, you can do that with the help of wrapper script as follow:

a. mv /sbin/shutdown /sbin/shutdown-orig
b. vim /sbin/shutdown #!/bin/sh echo "$USER has initiated the shutdown process" >> /var/log/shutdown.owner /sbin/shutdown-orig "$@"
c. chmod 755 /sbin/shutdown

2) Or, a normal user only has access to the shutdown command via sudo and sudo commands are (typically) logged under /var/log/. So, you can check that. Hope it helps. For further information, kindly refer to my thread here. Don't forget to stop by and say Thanks to them.

EDIT: Concluding, If nothing works, Try using sudo and walling off access to shutdown/reboot and then only you can check for logs and know who initiated the shutdown process. Detail's in content below. Thanks. Wonderful Question, Learnt a Lot.

share|improve this answer
    
This won't allow us to know which user is shutting down the system. Am I wrong? –  falconer Dec 28 '13 at 19:39
    
imho, consider adding who and getting the output on print statement that will let you know currently logged in users, or else, doing tail /var/log/auth.log | grep "username" should give you a user's sudo history. i don't think there is a way to get a unified command history of a user's normal + sudo commands. –  ASCIIbetical Dec 29 '13 at 8:36
    
you can use $USER variable to determine user –  c0rp Dec 30 '13 at 8:56
    
In that case as c0rp says, that can be done. –  ASCIIbetical Dec 30 '13 at 9:45
    
@ASCIIbetical I thought when those shutdown scripts run the users are already logged out, so there is nothing in the output of who. But I've never tried it, so my thought could have been wrong. Now I've tried it, but unfortunately it is the way I thought, no output from who. Doing some text searching and filtering in the logs to find out who was logged out last by lightdm might work, but obivously a simple tail-grep pair won't be enough. If you update your answer with a script which does filter out the username (only the username) of who clicked shutdown, that might be a solution. –  falconer Jan 1 at 10:23
show 14 more comments

LightDM

Create a script in /etc/rc0.d.

sudo vim /etc/rc0.d/myScript
sudo chmod +x /etc/rc0.d/myScript

GDM

Add your command to the file /etc/gdm/PostSession/Default before the exit 0 line.

As before shutdown the user is logged off anyway, this should cover both bases.

share|improve this answer
    
There is no /etc/gdm/PostSession/Default file. I'm using lightdm for instance. I've created it anyways, but that didn't help. That script is never run. –  Jorge Suárez de Lis Feb 1 '13 at 10:53
    
See the edit. Should work now.. –  abhshkdz Feb 1 '13 at 11:27
    
I need to know if a user is logging out, and what user, so that won't help. –  Jorge Suárez de Lis Feb 1 '13 at 11:43
    
Also, it would be better to stay on the an X session, because I need to show some output to the user. I'm adding this information to the main post. –  Jorge Suárez de Lis Feb 1 '13 at 11:53
add comment
up vote 0 down vote accepted

To handle this, I combined three mechanisms:

  • A Lightdm logout script, that gets the user information and writes it on a temporary file, so we can know who is powering off the computer. It also does the heavy task in case we're not shutting down or rebooting.
  • Traditional initrd scripts to do the heavy tasks when shutting down or rebooting.
  • Plymouth status messages to give feedback about that heavy tasks when shutting down or rebooting.

So, I have the heavy task script on /usr/local/bin/heavy.sh:

#!/bin/bash 
touch /tmpfile 
for p in $(seq 0 300) ; do
    sleep 1
    echo $p >> /tmpfile
    if [ ! -z $DISPLAY ] ; then
        notify-send "Written $p"
    else 
        plymouth message --text="Written $p" &>/dev/null
    fi
done

That heavy task tries to output information to X. If that fails, tries to do it to Plymouth.

Then, I added this line to the Lightdm configuration on /etc/lightdm/lightdm.conf:

session-cleanup-script=/usr/local/sbin/logout-tasks.sh

The referenced script writes down the user on logout and tries to do the heavy task:

#!/bin/bash
echo $USER > /run/last-logout-user
/usr/local/bin/heavy.sh

The initrd script, located on /etc/init.d/logout-heavy-task-at-shutdown:

#!/bin/bash
USER_RUN=$(cat /run/last-logout-user)
sudo -u $USER_RUN /usr/local/bin/heavy.sh

That launches the task as the last logged out user when shutting down and restarting, considering we add the corresponding links:

 update-rc.d -n logout-heavy-task-at-shutdown start 05 0
 update-rc.d -n logout-heavy-task-at-shutdown start 05 6

And that's it. The heavy task might need to handle when it's killed by X and then launched again by the initrd script. Depending on the task, that might not be a problem at all.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.