18

Is there a simple way to prevent the PC from going to sleep if there is high CPU activity? I need to run long processes overnight, so I want the PC to stay up while my processes are running, without any user activity, but when the processing is finished, the PC should go to sleep after the sleep timeout.

A solution with a "resetSleepTimer" function that I can call from my code (python ideally) would also be acceptable.


A clarification following comments from WinEunuuchs2Unix and Joaquín Ayuso de Paúl: unfortunately your solution works only if there is a single process, but I have normally more than one process running, with variable duration, so if one process ends and re-enables a short sleep timeout, it will sc*@w over the others still running. With resetSleepTimer function, I mean something to be called at regular intervals to reset the suspend timer. My previous (deleted) suggestion of simulating a user input wouldn't work, because it would also keep the screen ON.


Edit: a requirement as mentioned in a comment by OP:

Will this leave the screen on the whole time? Not what I'm looking for. Also, will acting on the screensaver also affect the sleep/suspend timeout?

4
  • 1
    Can't you just start all the processes from the single script, then disable sleep before starting this script and manually triggering it after it's finished? Or is there some way these processes start that prevents such solution?
    – Dan M.
    Nov 8, 2019 at 11:03
  • Or all of your processes write to a lock file or environment variable. And a seperate process watches this state and changes back the sleep timer after all processes delisted... or watch the processes via ps | grep whatever
    – Björn
    Nov 8, 2019 at 15:57
  • @Dan: honestly, no. I don't see why this can't be made completely transparent to the user. Really, it should be an option in the process that controls suspend (which one is it?): just like user activity resets the timer, so high CPU, polled at short intervals, should do the same. I guess I'm asking for a new feature in the suspend process, and I'm not alone, I've seen enough threads similar to mine, all without a simple solution. My request for something to insert in my code is really just a hack, not a proper solution.
    – thebucc
    Nov 9, 2019 at 13:42
  • @thebucc what you are asking for is a hack so only hacky solutions are possible. "CPU usage" doesn't really make sense - what is high? What if your CPU is fast enough that it is always underutilized? What if some scheduled unrelated task has started? It's to unreliable. To me it seems that you just want "go into sleep after the task has finished", which should have a proper solution.
    – Dan M.
    Nov 10, 2019 at 14:39

4 Answers 4

7

Based of from this thread, you can disable the sleep process through the duration of your program by calling to idle inhibition via DBus:

org.freedesktop.ScreenSaver.Inhibit

Or you can ping it periodically:

org.freedesktop.ScreenSaver.SimulateUserActivity

If you need to prevent the computer to sleep at all, you can disable temporally (again through dBus) the behavior and then reinstate it. This will kick the screensaver but won't let the computer sleep:

  $ sudo -u gdm dbus-launch gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing'
7
  • 1
    Will this leave the screen on the whole time? Not what I'm looking for. Also, will acting on the screensaver also affect the sleep/suspend timeout?
    – thebucc
    Nov 8, 2019 at 1:11
  • 1
    If you need to prevent the computer to sleep at all, you can disable temporally (again through dBus) the behavior and then reinstate it. This will kick the screensaver but won't let the computer sleep: $ sudo -u gdm dbus-launch gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing' Nov 8, 2019 at 1:29
  • Joaquin, I think I misunderstood your initial suggestion, and in fact org.freedesktop.ScreenSaver.SimulateUserActivity could be what I want. However, how do I use this line? It is not an executable command. And there's still the question whether this will also keep the screen on. Is there something similar that lets the screen go off, and only acts on the suspend timeout?
    – thebucc
    Nov 8, 2019 at 17:54
  • I've found several references to how to invoke the key you mention from command line, like this: qdbus org.freedesktop.ScreenSaver /ScreenSaver SimulateUserActivity > /dev/null I'll report back when I've verified that it works
    – thebucc
    Nov 8, 2019 at 18:38
  • 1
    @Mast, I'm a bit of an environmental freak: a PC sitting idly on is an unjustifiable waste of energy. The screen should go off within a couple of minutes, and the whole PC should go into suspend and later hibernation if there is no work to be done. All this should be automatic, without user intervention. It is all doable, but it is only dependent on user input, and I think it should also depend on CPU activity, as simple as that.
    – thebucc
    Nov 9, 2019 at 13:49
4

Discover your current sleep settings with this:

$ gsettings list-recursively | grep sleep
org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0
org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'suspend'
org.gnome.settings-daemon.plugins.power button-sleep 'suspend'
org.gnome.settings-daemon.plugins.power sleep-inactive-battery-timeout 0
org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type 'suspend'

My system is set to never go to sleep, but if yours is set for 5 minutes (300 seconds) it would look like this:

org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 300

When your python program starts issue the command:

gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0

When your python program ends restore the previous settings:

gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 300

Your screen saver settings are related at times:

$ gsettings list-recursively | grep top.screensaver
org.gnome.desktop.screensaver picture-opacity 100
org.gnome.desktop.screensaver logout-enabled false
org.gnome.desktop.screensaver lock-enabled false
org.gnome.desktop.screensaver logout-delay uint32 7200
org.gnome.desktop.screensaver embedded-keyboard-enabled false
org.gnome.desktop.screensaver primary-color '#023c88'
org.gnome.desktop.screensaver idle-activation-enabled true
org.gnome.desktop.screensaver secondary-color '#5789ca'
org.gnome.desktop.screensaver logout-command ''
org.gnome.desktop.screensaver color-shading-type 'solid'
org.gnome.desktop.screensaver embedded-keyboard-command ''
org.gnome.desktop.screensaver show-notifications false
org.gnome.desktop.screensaver picture-options 'zoom'
org.gnome.desktop.screensaver lock-delay uint32 0
org.gnome.desktop.screensaver show-full-name-in-top-bar true
org.gnome.desktop.screensaver picture-uri 'file:///usr/share/backgrounds/gnome/adwaita-lock.jpg'
org.gnome.desktop.screensaver status-message-enabled true
org.gnome.desktop.screensaver ubuntu-lock-on-suspend false
org.gnome.desktop.screensaver user-switch-enabled true

Edit script based on system activity

OP has clarified needs. Multiple jobs can be running. The first one that ends would reactivate sleep which will prevent remaining jobs from completing.

A scaled down version of this script is needed:

movie.sh status display 2.png

  • Removing dimming / brightening of monitors
  • Remove list of selective monitors to process
  • Remove checks for keyboard / mouse idle (which gnome uses for sleep activation)
  • Drastically reduce statistics summary screen or remove all together

Then the code using xprintidle (keyboard and mouse unused time) needs to be yanked out and replaced with:

$ uptime
 08:08:54 up 9 days,  3:38,  1 user,  load average: 0.30, 0.47, 0.71

The load average prints for 1 minute, 5 minutes and 15 minutes. Once 5 minutes or 15 minutes is below threshold, simply suspend the system.


Development testing

To start testing run this in a terminal now:

$ while true ; do uptime; sleep 300; done
 08:20:36 up 9 days,  3:50,  1 user,  load average: 0.36, 0.50, 0.64

Every five minutes the load average will display to give you an idea of where your thresholds should be to suspend.


Tracking usage

After program has been implemented you may want to audit usage. For tracking the suspend activity (power savings?) this script can be used:

$ suspendtime
Oct 31 05:55:19 to Oct 31 16:54:26 lasting 39,547 seconds
 (... SNIP ...)
Nov 08 07:24:31 to Nov 08 09:28:44 lasting 7,453 seconds
Nov 08 23:26:19 to Nov 09 07:38:50 lasting 29,551 seconds

Linux uptime 791,119 seconds (9 days, 3 hours, 45 minutes, 19 seconds)
18 Suspends 494,551 seconds (5 days, 17 hours, 22 minutes, 31 seconds)
Real uptime 296,568 seconds (3 days, 10 hours, 22 minutes, 48 seconds)
7
  • 1
    I think OP doesn't want to change things manually. Somehow, sleep should be prevented as long as CPU usage is above a certain value. Then, when the resource-intensive process is done, sleep should occur as it normally would. So maybe OP wants a while loop with something likeif ps -eo %C --sort -%cpu | awk 'NR==2 { exit !($1>10); }'; then ...? Depending on the OP, 10 maybe too low.
    – DK Bose
    Nov 8, 2019 at 2:27
  • 2
    @DKBose Yes OP did initially ask sleep deactivated based on CPU load. Then at end of question stated Python program could deactivate sleep at beginning and turn it back on at end. Nov 8, 2019 at 2:35
  • OK, but wouldn't that need the program to run for a specified preset time? If that's the case then you're right in not considering CPU usage at all.
    – DK Bose
    Nov 8, 2019 at 2:38
  • 3
    @DKBose I imagine the OP starts the python program before going to bed, then unsuspends machine in the morning to check results. Nov 8, 2019 at 2:40
  • @DK Bose: yes, what you say in your first comment is exactly what I think the sleep logic should be. I'm not sure what your script does (exit applies to what?), what I think should happen is: while(true) { if (high CPU activity, e.g. > 20-30%) { reset suspend timer; } sleep(1000); // millisec } (sorry I have no idea how to insert a new line!!)
    – thebucc
    Nov 9, 2019 at 14:08
0

You can use Keep.Awake python3 program to do exactly what you're after. It will solve your problem and it simply works!

It will take into account cpu load, user activity, and network traffic (boolean OR for all three).

You can get it from here: https://launchpad.net/keep.awake

It is written in python3 if you want to see how it works. Now supports up to Ubuntu 20.04

Example usage taken from the webpage:

To run as background service and set 15 min (900 sec) as the user activity idle time before it determines that the user is idle:

nohup ./keepawake.py -u 900 -r > /dev/null 2>&1 &

To run as background service and set minimum CPU load as 13%:

nohup ./keepawake.py -c 13 -r > /dev/null 2>&1 &

To run as background service and set minimum network traffic as 5KB (5120 bytes):

nohup ./keepawake.py -s 5120 -r > /dev/null 2>&1 &

To run as background service and set the schedule to sleep/suspend after 1 hour (this value is only set if user-activity, cpu, and network traffic are all determined to be idle) :

nohup ./keepawake.py -w 3600 -r > /dev/null 2>&1 &

To run all settings above (network, CPU, User idle, sleep schedule) in the one go and set the log-file path to "/home/$USER/sleep/log/Keep.Awake/" with detailed output:

nohup ./keepawake.py -s 5120 -c 13 -u 900 -w 3600 -l /home/$USER/sleep/log/Keep.Awake/ -v Detail -r > /dev/null 2>&1 &
0

I developed a script that can inhibit on high cpu percentage (percentage can be set), specified open windows (you can specify the name of the window, the name of the application and the window count of a specific application) or running audio. Unfortunately, I'm not sure if it will work for your distro. My script uses the psutil python library and the systemd-inhibit, so you might want to run that command (systemd-inhibit) in the terminal to see if there is a chance that it will work. (It should list things that delay and block sleep and so on).

I hope this helps. If there are problems, feel free to open an issue or write about it here.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .