#!/bin/bash ARGS=$1; SCRIPTNAME=${0##*/}; SCRIPTNAME=${SCRIPTNAME#*_} ################################################################################ # # mintupdate-on-wakeup by tux@enkidu.eu # # (based on unattended-upgrades-alternative 1.1 by tux@enkidu.eu) # # 28.12.2018: v1.0 - initial release # ################################################################################ AUTHOR="tux@enkidu.eu"; VER=1.0 ############################################################################### # # This is a simple replacement for "unattended-upgrades". # It is NOT thought for server usage! # It is thought for e.g. users with a notebook, where normal usage is # open notebook = resume/wakeup # close notebook = hibernate/suspend # # Script is executed after each wakeup and update done 2-3 times a day. # (Not at every resume, only if first digit of 2 digit hour changes. # E.g. 0x (00, 01, 02, ...), 1x, 2x) # ################################################################################ ################################################################################ # # >>> Use it on your own risk! <<<< # ################################################################################ ################################################################################ # # Installation: # ------------- # # Place this script in $HOME/bin # # > chmod 755 $HOME/bin/mintupdate-on-wakeup # > sudo ln -s $HOME/bin/mintupdate-on-wakeup /lib/systemd/system-sleep/ # # # If you want to check for updates after login, you have to add # # sudo $HOME/bin/mintupdate-on-wakeup login # # to your # # $HOME/.profile # # AND edit your sudoers config accordingly that it can be run without pw! # # # IMPORTANT: Please see also configuration below! # ################################################################################ ################################################################################ # # Usage: # ------ # # For testing purposes you can invoke it like # # > sudo ./mintupdate-on-wakeup post # # # To clean logs, index, tmp, start it with # # > sudo ./mintupdate-on-wakeup cleanup # ################################################################################ ################################################################################ # # See /var/log/mintupdate-on-wakeup.log for log! # ################################################################################ #=============================================================================== # # User configuration # # Your mintupdate-tool settings (-r -y is added by default) # See "mintupdate-tool --help" for details MUTOPTS="-k -s -l 1234" # if mintupdate-tool returns with error, automatically open Mint Update GUI? OPENUPDGUIONERR=true # or false # Delay in minutes the script waits before mintupdate-tool is started UPDATEDELAY=2 # minimum = 1! # Desktop notifications # # Prerequisite: libnotify-bin # If not installed it will simply not notify! :) # Level 0: disable desktop notifications # 1: errors # 2: warning # 3: info # 4: verbose # 5: debug # # For normal usage, I suggest to use 2. NOTIFY_LEVEL=5 # The following variables only need to be changed if the values returend # do not fit your needs! # Icons used for notification. Change only if they do not fit or do not exist NOTIFY_ICON_AVAIL="/usr/share/icons/hicolor/24x24/status/mintupdate-updates-available.png" NOTIFY_ICON_CHECK="/usr/share/icons/hicolor/24x24/status/mintupdate-checking.png" NOTIFY_ICON_ERROR="/usr/share/icons/hicolor/24x24/status/mintupdate-error.png" NOTIFY_ICON_INSTALL="/usr/share/icons/hicolor/24x24/status/mintupdate-installing.png" #NOTIFY_ICON_AVAIL="/usr/share/icons/hicolor/48x48/status/mintupdate-updates-available.png" #NOTIFY_ICON_CHECK="/usr/share/icons/hicolor/48x48/status/mintupdate-checking.png" #NOTIFY_ICON_ERROR="/usr/share/icons/hicolor/48x48/status/mintupdate-error.png" #NOTIFY_ICON_INSTALL="/usr/share/icons/hicolor/48x48/status/mintupdate-installing.png" # Here you may manually enter the value you get in a normal terminal when typing # > echo $DISPLAY # BUT ONLY change it, if the display could not properly be detected! DESKTOP_DISPLAY=":$( ls /tmp/.X11-unix/* | head -1 | sed 's:/tmp/.X11-unix/X::' )" # What is the name of the desktop user you are working with? # Some commands need to be invoked inside your user context or it does not work. # BUT ONLY change it, if the user could not properly be detected! DESKTOP_USER=$( who | grep '('$DESKTOP_DISPLAY')' | head -1 | awk '{print $1}' ) # # End of user configuration # #=============================================================================== ################################################################################ ################################################################################ ## ## DO NOT EDIT BELOW IF YOU DO NOT REALLY KNOW WHAT YOU ARE DOINT!!! ## ################################################################################ ################################################################################ [ $USER != root ] && { echo " $SCRIPTNAME: This script must be run as root! Usage: sudo $SCRIPTNAME < | | clean > " exit 1 } log() { # $1: log message level # 2: text # 3: additional text DT=$( date +'%Y-%m-%d %H-%M-%S' ) printf "%s | %5d | %d - %s\n" "$DT" $$ $1 "$2" [ ! -z "$3" ] && printf "%s | %5d | %s %s\n" "$DT" $$ ' ' "$3" # send desktop notification [ -z "$NOTIFY_SEND" ] && return (( NOTIFY_LEVEL < $1 )) && return case $1 in 1) ICO=$NOTIFY_ICON_ERROR; URG=critical;; 2) ICO=$NOTIFY_ICON_INSTALL; URG=normal;; 3) ICO=$NOTIFY_ICON_AVAIL; URG=low;; 4) ICO=$NOTIFY_ICON_CHECK; URG=low;; 5) ICO=$NOTIFY_ICON_CHECK; URG=low;; esac IC='' [ -r $ICO ] && IC="-i $ICO" || echo >&2 "ERROR: unable to read icon '$ICO'!" BODY="$2" [ ! -z "$3" ] && BODY+="\n$3" TITLE=$( printf "%-70s" "<< $SCRIPTNAME >>" ) # notify-send -a $SCRIPTNAME $IC -u $URG "$TITLE" "$BODY" su -c "$NOTIFY_SEND -a $SCRIPTNAME $IC -u $URG '$TITLE' '$BODY'" $DESKTOP_USER } quit() { log 5 "*** $SCRIPTNAME ended ***" echo exit $1 } tfunc() { type $1 | sed -n '2,$p' } # some presets LOG_FILE=/var/log/$SCRIPTNAME.log CHECKUPDRUNNING="ps -ef | fgrep -v grep | egrep 'apt-get|dpkg|mintupdate-tool' | wc -l" NOTIFY_SEND=${NOTIFY_SEND:-notify-send} which $NOTIFY_SEND >/dev/null 2>&1 || NOTIFY_SEND='' # get DBUS of user (it is tricky and might not work for all...) [ -z "$DBUS_SESSION_BUS_ADDRESS" ] && { DUID=$( pgrep -l "(cinnamon|gnome|kde|mate|xfce)" | fgrep "-sessio" | awk '{ print $1 }' ) DSBA=$( grep -z "^DBUS_SESSION_BUS_ADDRESS" /proc/$DUID/environ ) export DBUS_SESSION_BUS_ADDRESS=${DSBA#*=} } # check DISPLAY [ -z "$DISPLAY" ] && \ export DISPLAY="$DESKTOP_DISPLAY" LASTRUN_INDEX=/var/tmp/$SCRIPTNAME.lastrun TMP_FILE=/var/tmp/$SCRIPTNAME.tmp # redirect all output to logfile exec >>$LOG_FILE exec 2>&1 log 5 "*** $SCRIPTNAME v$VER by $AUTHOR started ***" "[ \$1='$ARGS'; USER=$DESKTOP_USER; DISPLAY=$DISPLAY}; DSBA=$DBUS_SESSION_BUS_ADDRESS ]" [ -z "$DBUS_SESSION_BUS_ADDRESS" ] && \ log 2 "WARNING: DBUS_SESSION_BUS_ADDRESS could not be detected! Desktop notifications might not work!" \ "Please contact $AUTHOR and provide infos about your environment to fix this problem!" case "$ARGS" in post|resume|thaw|login) log 4 "## Wakeup ($ARGS)" # read last run LASTRUN=`cat $LASTRUN_INDEX 2>/dev/null || echo 0` NOW=`date "+%Y%m%d%H" | cut -b 1-9` # Skip, if update already in progress! if (( `eval "$CHECKUPDRUNNING"` )); then log 3 "Skipped! (Update in progress!)" # Skip update if in same hour range elif (( LASTRUN == NOW )); then log 3 "Skipped! Already done a while ago." "[ Last $LASTRUN == Now $NOW ]" # Check & install updates else # run this part in background, otherwise it will conflict with other wakeup scripts! cat > $TMP_FILE <<__EOT__ #!/bin/bash trap "" 1 2 3 15 LOG_FILE=$LOG_FILE SCRIPTNAME=$SCRIPTNAME exec >>$LOG_FILE exec 2>&1 export DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS export DISPLAY="$DESKTOP_DISPLAY" `set | egrep '^DISPLAY|^XAUTHORITY' | while read L; do echo "export $L"; done` `set | egrep '^DESKTOP_|^NOTIFY_'` `tfunc log` `tfunc quit` log 5 "Background process initiated from PID \$1" "[ DESKTOP_USER=$DESKTOP_USER; DISPLAY=$DISPLAY ]" # check internet connection first log 4 "Checking connectivity..." I=0 while true do (( I > 20 )) && { log 1 "ERROR: could not detect internet connectivity!" quit 1 } let I=I+1 DG=\$( ip r | fgrep default | awk '{ print \$3; }' ) [ -z "\$DG" ] && { log 5 "> No default gateway found, waiting 10sec for interface..." sleep 10 continue } ping -c 1 -q -W 3 \$DG || { log 5 "> default gateway '\$DG' is not reachable, waiting 10sec to try again..." sleep 10 continue } ping -c 1 -q -W 3 www.google.com || { log 5 "> www.google.com is not reachable, waiting 10sec to try again..." sleep 10 continue } break done log 4 ">> Ok!" log 3 "Starting Mint Update!" "[ Last $LASTRUN != Now $NOW ]" mintupdate-tool -r -y $MUTOPTS upgrade \ && log 4 "> mintupdate-tool finished with no error" \ || { log 1 "> mintupdate-tool returned error \$?!" ">> Check $LOG_FILE for details & retry using mintupdate gui!" [ "$OPENUPDGUIONERR" == "true" ] \ && echo "su -c 'export DISPLAY=$DESKTOP_DISPLAY; mintupdate'" $DESKTOP_USER | at now } echo >$LASTRUN_INDEX "$NOW" quit 0 __EOT__ log 5 "Starting update background process in $UPDATEDELAY min..." "[ $TMP_FILE ]" chmod +x $TMP_FILE echo $TMP_FILE $$ | at -M now + $UPDATEDELAY min # Using at was the only way I could find that my child process was not killed # (nor disown & or hohup & did survive - dunno why!?) or caused strange # side effects. Using at everything works perfect! :) fi ;; pre|hibernate|suspend) log 4 "## Suspend ($ARGS)" # if going in hibernate/suspend just wait a moment if an update is running. # But even if, it should be continued after resume... # So no complicated hibernate handling is required. let I=0 while (( `eval "$CHECKUPDRUNNING"` )) do (( I == 10 )) && break (( ! I )) && log 2 "> Running updates detected!" "Waiting max. 100sec to go to sleep ($ARGS)..." (( I )) && log 4 "> ... $I" sleep 10 let I=I+1 done (( ! I )) && log 5 "> No running updates detected." quit 0 ;; cleanup) rm -f $LASTRUN_INDEX $LOG_FILE $TMP_FILE >/dev/null 2>&1 log 4 ">> Cleanup finished <<" ;; *) log 1 "Mode '$ARGS' ist not supported!" "Please report to $AUTHOR if it was not a cmdline try by yourself!" quit 1 ;; esac