4

I have just restarted my Ubuntu, but I forgot that a virtual machine was open in the background (having a minimized icon on the taskbar). Is it possible to configure Ubuntu in a way that if a user-defined application is running, then issue a warning before restart/shutdown? I am using version 16.04.

  • yes, possible to do so. In fact, your question is ( somewhat ) a duplicate of How can I run a local command (to run a script) on (just before) log out of a Unity session? . What is the level of programming skill ? – Sergiy Kolodyazhnyy May 12 '16 at 9:51
  • I can follow instructions, and I have administrative privileges. I need to check the (quite detailed) answer you referenced. – Matsmath May 12 '16 at 9:53
  • Let me know if that would be a sufficient information for you , and also implementation of the method I show there has been used on another question, Prevent Ubuntu from shutdown before background automatic updates complete . I can always adapt the script there for your question, and if you need more features , we can discus that – Sergiy Kolodyazhnyy May 12 '16 at 9:57
  • All right, the script works (I tested it with top running), as long as it is manually started from a terminal. I created a .desktop file just like this (with the obvious modifications), and it indeed shows up in the Startup applications app. However, it does not seem to be working. – Matsmath May 12 '16 at 12:50
  • Creating the file alone doesn't mean it will show up, that file must be placed into ~/.config/autostart folder. I'll post an answer later today when i have time. – Sergiy Kolodyazhnyy May 12 '16 at 18:39
3

Introduction

The script bellow monitors all or user-defined application for presence, and if that presence is found - the system will be prevented from shutting down via graphical dialog ( the shutdown via command line won't be affected , as this is task applied by system administrators who know what they're doing).

There are 3 options:

-a Monitor any open applications.

-c Graphically select an app

-s specify .desktop file for app on command line

-h prints the syntax and list of options.

The -c option is appropriate for one session only, where you want to simply click on a window and monitor that. The -a and -s options are appropriate to be added as autostart entries to be launched on system login. -s option can be used with either full path or a portion of it , e.g. either /usr/share/applications/firefox.desktop or firefox.desktop are equally acceptable.

Script Source

The script source is available here or on my GitHub. Users can obtain the script either via cloning the whole repository or using

wget https://raw.githubusercontent.com/SergKolo/sergrep/master/safe_shutdown.sh && chmod +x safe_shutdown.sh

command to obtain just the script itself.

#!/usr/bin/env bash
#
###########################################################
# Author: Serg Kolo , contact: 1047481448@qq.com 
# Date: May 14th , 2016 
# Purpose: Ensure that user closes all or specific
#          running windows and exits without any work
#          lost
# Written for: http://askubuntu.com/q/771227/295286
# Tested on: Ubuntu 14.04 LTS
###########################################################
# Copyright: Serg Kolo , 2016
#    
#     Permission to use, copy, modify, and distribute this software is hereby granted
#     without fee, provided that  the copyright notice above and this permission statement
#     appear in all copies.
#
#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
#     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#     DEALINGS IN THE SOFTWARE.

ARGV0="$0"
ARGC=$#

_notify_user()
{
 # Close the shutdown dialog and display
 # graphical popup which will ask user's shutdown 
 # confirmation. If user clicks OK , we shutdown.
 # If cancel - no action.
 qdbus com.canonical.Unity \
       /com/canonical/Unity/Session \
       com.canonical.Unity.Session.CancelAction

 if zenity --question --title='WARNING!' \
      --text="You have running apps. Shutdown anyway ?" \
      2> /dev/null
 then
      qdbus com.canonical.Unity  \
           /com/canonical/Unity/Session \
           com.canonical.Unity.Session.Shutdown
 fi
}

_get_running_apps()
{
  # Gets list of .desktop files for each
  # running app
  qdbus org.ayatana.bamf \
       /org/ayatana/bamf/matcher \
       org.ayatana.bamf.matcher.RunningApplicationsDesktopFiles 

}

_check_any_running()
{
   # Among the running apps there's always one
   # .desktop file, which is compiz.desktop. 
   # We want to know if there's anything besides that
   if [ $( _get_running_apps | wc -l ) -gt 1  ]; 
   then
         _notify_user
   fi
}

_check_specific_running()
{
  # Get list of running apps and see if
  # the .desktop file we got is on the list
  if _get_running_apps | grep -q "$1"
  then
       _notify_user
  fi
}

_select_app()
{
  # xwininfo provides nice interface which allows selecting
  #  a window. The rest is just simple parsing and passing 
  # around the XID of the app.
  notify-send 'Select a window you would like to monitor '
  XID=$(xwininfo -int | awk '/xwininfo: Window id/{print $4}')
  APP=$(qdbus org.ayatana.bamf \
       /org/ayatana/bamf/matcher \
       org.ayatana.bamf.matcher.ApplicationForXid  $XID )
  qdbus org.ayatana.bamf \
        "$APP" org.ayatana.bamf.application.DesktopFile
}


_print_usage()
{
 cat <<EOF
 safe_shutdown.sh [-a | -c |-s DESKTOP_FILE | -h  ]

 Options:
 -a Monitor any open applications.
 -c Graphically select an app
 -s specify .desktop file for app on command line
 -h print this text

  Copyright Serg Kolo , 2016
EOF
}

parse_args()
{
 if [ $ARGC -eq 0 ] ; then
   printf "%s: No option specified\n Usage:\n" ${ARGV0##*/} 
   _print_usage 
   exit 1
 fi

 local OPTIND opt
 while getopts "acs:" opt
 do
   case ${opt} in
      a) FUNCTION="_check_any_running"
        break
        ;;
      c)
        DESK_FILE=$(_select_app  )
        FUNCTION=" _check_specific_running $DESK_FILE   "
        break
        ;;

      s) DESK_FILE=${OPTARG}
         FUNCTION=" _check_specific_running $DESK_FILE   "
         break
        ;;
      h) _print_usage
        exit 0
        ;;
     \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    esac
  done
  shift $((OPTIND-1))

}


main()
{
 # Basic idea is to let user chose what to do
 # then monitor dbus for appropriate signal
 # Once the RebootRequested signal is received 
 # then perform appropriate checks ( for a specific
 # or all apps ). 
 local FUNCTION
 parse_args  "$@"
 dbus-monitor --profile \
      "interface='com.canonical.Unity.Session',type=signal" |
 while read -r line;
 do
  case "$line" in
       *RebootRequested*)  $FUNCTION ;;
  esac
 done
}

main "$@"
| improve this answer | |
  • 1
    I continuously get surprised how much one can do with a few lines of code. Obviously, it will take some time to fully go through this stuff, which is highly appreciated. – Matsmath May 14 '16 at 17:25
  • @Matsmath Always glad to assist.Let me know if you need any other features added to this script – Sergiy Kolodyazhnyy May 14 '16 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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