Recently I ran a long-running script that I started from a Terminal window in Ubuntu 16.04 x64. When I walked away from the system, it eventually suspended automatically after the 20 minutes that I had it configured to in the System Settings
window, which had the effect of pausing the script. When I returned to the system, I realized that several hours of progress on the execution of my script was lost because the system had suspended.
One workaround is to manually select Don't suspend
in the Power
settings window chosen from System Settings
. This method to prevent suspend is unsatisfactory (1) because I often forget to do it, and (2) because it makes me subservient to my system.
Perhaps there's a slicker but still manual way of doing this with some kind of prefix command, which I'll call nosuspend
for now, with this usage: nosuspend python myscript.py arg1 arg2
. My main gripe with this mythical command is that it still requires that I remember to use it, and, since it's unreasonable to prefix all terminal commands, one has to predict whether a script will take 1 minute or 1 hour to run, and this prediction may be incorrect, leading again to time loss and frustration.
Ideally, the solution would prevent suspend until all commands run from a Terminal window complete. At some level, I realize this is impossible, as a bash process within the Terminal window may well have a subprocess that we may not want to prevent sleep, e.g., sudo su
executed in a Terminal window is still running even though we may not be currently using it, and is thus idle, but we still want the system to suspend automatically after 20 minutes, say. So, there is a problem of defining criteria for suspend.
I must note that the Python script in question had only sporadic disk, network, and almost no CPU work, as it had repeated Python time.sleep() calls of up to less than a minute per call. Therefore, I'm not particularly looking for methods that merely detect a "fairly" quiescent state in disk, network, or CPU. Perhaps there's a way to detect if a command that is a subprocess of Terminal has made any progress at all during an interval (hopefully the same interval configured in Power
above). Hopefully that would distinguish my script from the above idle sudo su
counter-example.
Update 1 (14-September-2016):
As recommended by Adrine Correya below, I tried systemd-inhibit
, which sounds like the imagined nosuspend
above, but it didn't work. Here's what I did. First I created a Python test script called "long-job.py":
#!/usr/bin/python3
import time
print("starting")
for i in range(10):
time.sleep(10)
print("epoch", i)
print("all done")
Then I made it executable using chmod +x long-job.py
. To speed up testing, I set org>gnome>settings-daemon>plugins>power>sleep-inactive-ac-timeout
to 20 (seconds) using dconf-editor
(installed via Ubuntu Software). I then ran the script, without root/sudo, using systemd-inhibit ./long-job.py
, but the system still went to sleep before the job was finished (it should take around 100 seconds to run, but sleep happened after 20 seconds). I also tried a few of the options (--what="sleep"
and --what="idle"
) but it still didn't work. According to the man page, the default is --what="idle:sleep:shutdown"
.
Update 2 (14-September-2016):
On Mac OS X, it seems that caffeinate
actually implements the nosuspend
idea above; see https://superuser.com/questions/99247/stop-a-mac-from-sleeping-while-a-bash-script-is-running-then-allow-it-to-sleep. Again, it would be nice to have this automated, so we don't have to guess which jobs might be long-running. Also, a Ubuntu version is needed.
systemd-inhibit
if user selects suspend from the UI. I've found that inhibit does work correctly if I use both:systemd-inhibit --what "sleep:handle-suspend-key" mate-session-inhibit --inhibit suspend <COMMAND TO RUN>
– Mikko Rantalainen Jun 04 '21 at 08:10