KDE5 switch hibernate / suspend in night / day

Hi

I’ve been looking for a command line way to switch KDE5 power management to suspend or to hibernate, so I can have a script which will, when I wake the computer, set the next sleep according to whether it’s day or night, i.e. after 11pm, hibernate at next sleep, after 8am suspend at next sleep.

Can anyone point me to the right bit of documentation / dbus commands / whatever?

Thanks
David

p.s. I’ve searched, and there’s lots of old stuff that no longer works, but nothing recent I can see …

KDE’s power management utility can be configured to run a script after a certain period of inactivity. Such a script could check the current time, then suspend (‘systemctl suspend’ command) or hibernate (‘systemctl hibernate’ command) as appropriate

System Settings > Power Management > Energy Saving > Run Script…

Many thanks. I’ll do that this weekend. :slight_smile:

OK. Thanks. That works. :slight_smile:

Another related question: I was trying to be clever and not sleep if certain jobs are running (ffmpeg, transcode for media conversion unison, rsync for backups etc.). I have two options for this: return a non-zero return code; or wait until the job has finished and do the sleep then. The former is dependent on whether (and when) the power management software retries later if the sleep fails, and the later would benefit if the script could recognise if someone had removed / closed the screen locker.

Is there a “universal” (within X11) way to tell if a screen locker has locked the screen?

Thanks
David

I don’t know about a completely ‘universal’ method since it might depend on the DE in use, but one approach to listen to dbus…

Thanks for all the contributions. I’ve built a script which works for me, offered for others here:

#!/bin/sh
# check if suspend is OK, and do it

MyName="$( basename "$0" '.sh' )" || MyName="$0"
logger --tag "$MyName" $0 $@

# Get parameters
 -f "$HOME/.$MyName.conf" ] && . "$HOME/.$MyName.conf"

# Numeric with default & minimum value
numeric ()
{
  if echo "$1" | egrep -q '^([1-9][0-9]*|0)$' ; then
    if echo "$3" | egrep -q '^([1-9][0-9]*|0)$' &&  $3 -gt $1 ] ; then
      echo "$2"
    else
      echo $1
    fi
  else
    echo "$2"
  fi
}

DEBUG=$( numeric "$DEBUG" 0 )

 -n "$BlockList" ] || BlockList='ssh vnc'
 -n "$SuspendAfter" ] && echo "$SuspendAfter" | egrep -q '^[0-9]{4}$' || SuspendAfter='0800'
 -n "$HibernateAfter" ] && echo "$HibernateAfter" | egrep -q '^[0-9]{4}$' || HibernateAfter='2200'
SuspendCmd="systemctl suspend"
HibernateCmd="systemctl hibernate"

RetryInterval=$( numeric "$RetryInterval" 5 1 ) # seconds
QuietTime=$( numeric "$QuietTime" 60 ) # seconds
MaxTime=$( numeric "$MaxTime" 300 ) # seconds
QuietIntervals=$(( $QuietTime / $RetryInterval +1 ))
MaxIntervals=$(( $MaxTime / $RetryInterval +1 ))

dbusPath=''
for X in org.freedesktop.ScreenSaver org.kde.ScreenSaver org.gnome.ScreenSaver ; do
  if qdbus $X /ScreenSaver &>/dev/null ; then
    dbusPath=$X
    break
  fi
done
 -z "$dbusPath" ] && dbusCmd='' || dbusCmd="qdbus $dbusPath /ScreenSaver $dbusPath"

 $DEBUG -lt 2 ] || logger --tag "$MyName" "BlockList=$BlockList"
 $DEBUG -lt 3 ] || logger --tag "$MyName" "SuspendAfter=$SuspendAfter HibernateAfter=$HibernateAfter"
 $DEBUG -lt 3 ] || logger --tag "$MyName" "RetryInterval=$RetryInterval QuietTime=$QuietTime QuietIntervals=$QuietIntervals MaxTime=$MaxTime MaxIntervals=$MaxIntervals"
 $DEBUG -lt 3 ] || logger --tag "$MyName" "dbusPath=$dbusPath dbusCmd=$dbusCmd"


Retries=$QuietIntervals
while  $Retries -gt 0 ] ; do
  Retries=$(( $Retries - 1 ))
  MaxTime=$(( $MaxTime - 1 ))
  
  # Screensaver no longer active?
   $DEBUG -ge 3 ] &&  -n "$dbusCmd" ] && logger --tag "$MyName" "ScreenSaver.GetActive=$( $dbusCmd.GetActive )"
   -z "$dbusCmd" ] || if $dbusCmd.GetActive | egrep -qi '^:space:]]*false:space:]]*$' ; then
     $DEBUG -lt 1 ] || logger --tag "$MyName" "Exiting as ScreenSaver no longer active"
    exit 127
  fi
  
  for X in $BlockList ; do
    killall -s 0 --quiet "$X" && break
  done
  if  $? -eq 0 ] ; then
     $DEBUG -lt 2 ] || logger --tag "$MyName" "$X still active"
    Retries=$QuietIntervals
  fi

  if  $Retries -gt 0 ] ; then
    # Don't run twice
    if  -n "$( pidof -s -x -o %PPID "$0" )" ] ; then
      logger --tag "$MyName" "Exiting as $0 is already running."
      exit 127
    fi
    
    # Don't wait too long
    if  $MaxTime -le 0 ] ; then
       -z "$dbusCmd" ] || $dbusCmd.SimulateUserActivity
      exit 127
    fi

     $DEBUG -lt 3 ] || logger --tag "$MyName" "$Retries sleep $RetryInterval"
    sleep $RetryInterval
  fi
    
done

TIME="$( date '+%H%M' )"
 $DEBUG -lt 3 ] || logger --tag "$MyName"  "$TIME $SuspendAfter $HibernateAfter"
if  -n "$TIME" ] &&  -n "$SuspendAfter" ] &&  -n "$HibernateAfter" ] &&  -n "$SuspendCmd" ] &&  -n "$HibernateCmd" ] ; then
  if  "$SuspendAfter" \< "$HibernateAfter" ] ; then
    if  "$SuspendAfter" = "$TIME" ] || (  "$SuspendAfter" \< "$TIME" ] &&  "$TIME" \< "$HibernateAfter" ] ) ; then
       $DEBUG -lt 2 ] || logger --tag "$MyName" "$SuspendAfter le $TIME and $TIME lt $HibernateAfter"
       $DEBUG -lt 1 ] || logger --tag "$MyName" $SuspendCmd
      exec $SuspendCmd
    else
       $DEBUG -lt 2 ] || logger --tag "$MyName" "$SuspendAfter gt $TIME or $TIME ge $HibernateAfter"
       $DEBUG -lt 1 ] || logger --tag "$MyName" $HibernateCmd
      exec $HibernateCmd
    fi
  else
    if  "$HibernateAfter" = "$TIME" ] || (  "$HibernateAfter" \< "$TIME" ] &&  "$TIME" \< "$SuspendAfter" ] ) ; then
       $DEBUG -lt 2 ] || logger --tag "$MyName" "$SuspendAfter gt $TIME and $TIME ge $HibernateAfter"
       $DEBUG -lt 1 ] || logger --tag "$MyName" $HibernateCmd
      exec $HibernateCmd
    else
       $DEBUG -lt 2 ] || logger --tag "$MyName" "$SuspendAfter le $TIME or $TIME lt $HibernateAfter"
       $DEBUG -lt 1 ] || logger --tag "$MyName" $SuspendCmd
      exec $SuspendCmd
    fi
  fi
fi

exit 0

It, as usual comes with no warranties or guarantees. Use at your own risk!

Nice work. I’m sure it will be of value for others who come searching. :slight_smile:

A word of warning about this script: it won’t detect if a program (e.g. dd) is being run by another user (e.g. as root using sudo)!

This deficiency can be fixed using additional entries in /etc/sudoers to permit killall -s 0 - [A-Za-z0-9]* (not tested) and more code in the script to detect if this is present and use it if so, but this is too much messing about for me now.

If someone fixes this, please repost or put on githib …