UPDATE (2016-06-11) : Desde a primeira vez que escreveu o script, ele se tornou um programa completo que determina quando suspender com base em
- Tráfego de rede
- Atividade do usuário
- carga da CPU
Publiquei-o no Launchpad aqui link sob uma licença GPL.
Não existe um pacote de snap ou deb ainda, mas eu irei contorná-lo eventualmente.
Enquanto isso, você pode baixar este e descompactá-lo para usar.
Funciona como um comando adequado.
Digite --help para ver uma lista completa do que pode ser feito. Os exemplos abaixo são apenas alguns: ./keepawake.py --help
Para executar interativamente:
./keepawake.py
Para ser executado como um serviço de segundo plano:
nohup ./keepawake.py -r > /dev/null 2>&1 &
Para executar como serviço em segundo plano e definir 15 min (900 seg) como o tempo ocioso da atividade do usuário antes de determinar que o usuário está ocioso:
nohup ./keepawake.py -u 900 -r > /dev/null 2>&1 &
Para executar como serviço de segundo plano e definir uma carga mínima de CPU de 13%:
nohup ./keepawake.py -c 13 -r > /dev/null 2>&1 &
Para executar como serviço de segundo plano e definir um tráfego de rede mínimo de 5 KB (5120 bytes):% nohup ./keepawake.py -s 5120 -r > /dev/null 2>&1 &
Para executar todas as três configurações acima (rede, CPU, usuário inativo) de uma só vez:
nohup ./keepawake.py -s 5120 -c 13 -u 900 -r > /dev/null 2>&1 &
[ORIGINAL POST] :
Com base na resposta do dhiya, modifiquei o script. Ele lida com tráfego de rede e atividade do usuário !
Eu tive que nomear algo, então eu chamei de "Keep Awake".
Dê uma olhada e responda se tiver alguma pergunta ou comentário!
Notas da versão ...
- Verifica a atividade do usuário e o tráfego de rede com base nos limites
- Se um ou ambos estiverem acima dos limites, as configurações de energia de suspensão do sistema operacional serão desativadas.
- Minha primeira modificação do código trouxe para o Python 2.7.x eu tive que migrar de volta para o 3.4.x
- Implementou uma impressão que vai para um arquivo de log e uma saída padrão usando os recursos do python 3.
- Adicionadas muitas impressões de dados para determinar o estado. Muito útil para solucionar problemas.
- Na lógica If-elif-else, adicionei contadores de contagem regressiva.
- Adicionamos muitos comentários, e esperamos que ajudem aqueles que são novatos em tudo isso.
- Agrupou uma configuração de logrotate que você pode usar para gerenciar os logs de saída indefinidamente para sempre. (Veja os comentários na história)
- É altamente recomendado que o cron logrotate seja movido para cron.hourly
- Faz uso de xprintidle
- logrotate config faz uso do xz-utils
- O teste de desempenho repetido mostrou que o impacto da CPU é virtualmente insignificante. Somente o algoritmo de compactação xz executado pelo logrotate pode impactar um único núcleo em até 100%. Mas não dura muito tempo em CPUs modernas, além de ser de encadeamento único. Então seus outros núcleos podem fazer outro trabalho. Ele só compactará logs com dois dias ou maiores que 20 MB.
- Quando estiver satisfeito com a configuração, você poderá configurá-lo usando o iniciador integrado de aplicativos de inicialização da distribuição, que iniciará o programa após o login na sua conta. Certifique-se de ter logrotate configurado com a configuração de script abaixo para gerenciar os arquivos de log. Você pode ajustar isso para o seu prazer também.
- 16/09/2015 - versão 2.1 - Adicionado a lógica do Force Graceful Suspension
- 16/09/2015 - versão 2.1 - O programa agora é projetado para ser executado com privilégio de sudo e logar em /var/log/Keep.Awake/. logrotate config agora será padronizado para processamento multicore para compressão e só rotacionará se for maior que 1M. Isso requer xz-utils > = v5.2.0
Comando de exemplo para ser executado em segundo plano
$ sudo nohup python3 Keep\ Awake.v2.py > /dev/null 2>&1 &
FILENAME: "Keep \ Awake.v2.py"
#!/usr/bin/env python3
import subprocess
import time
import logging
import datetime
import sys
#--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# Keep Awake
# version: 2.1
#
# PURPOSE:
# This program will check 'network traffic' AND 'user activity' and decide whether to enable the timer to suspend or cancel it.
#
# METHOD:
# The program checks the network traffic if it is greater than a certain treshold; if so it keeps the system awake; if not it checks for user activity.
# If the user activity is idle for a time greater than a treshold then it sets the timer to suspend.
#
# SAMPLE RUN COMMAND:
# sudo nohup python3 Keep\ Awake.v2.py > /dev/null 2>&1 &
#
# History:
# 2015-08-22 DanglingPointer - Modified from https://sobrelinux.info/questions/32177/is-there-any-way-to-make-ubuntu-not-to-suspend-while-a-download-in-progress"Keep Awake".
# - Version two now prints to standard output as well as a log file information useful for troubleshooting.
# - Comes with a "Kee,Awake.v2.logrotate.config" file which can be used with linux logrotate.d. It is recommended that logrotate be moved to cron.hourly.
# - Upgraded coded from Python 2 to 3 using 2to3 command.
# - Requires xprintidle linux package.
# 2015-09-16 DanglingPointer - Modified to version 2.1. Added logic to "gracefully force suspension" if automatic suspension fails to happen. This has been observed to happen when
# - the setting to require a password after suspension is enabled locking the desktop. Keep.Awake.v2.1 will now send a dbus message to force graceful suspension.
# - **NOTE 1** "Force Graceful suspension" will ONLY work in this version if the program is run as root (sudo privilege) after logging into a user account.
# - **NOTE 2** "Force Graceful suspension" will NOT work if the program is sudo-run from command prompt without logging into a user desktop. (i.e. Fails when: run from CTL+ALT+F2 before login OR run from prompt after "switch user" is selected after locking desktop -> in that order)
#--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
# CONFIG
suspend_wait = 3600 # set suspend time (seconds); In Ubuntu 14.04 it needs to be the equivalent of one of the options from the Power Settings or else it may not work.
speed_limit = 1024 # set a minimum speed (bytes/second) to be considered a download activity
looptime = 20 # time interval between checks (seconds)
download_wait = 300 # time (seconds) to wait after the last download activity before suspend is re-activated.
userIdle = download_wait*1000 # user activity idle time in miliseconds before suspend is re-activated, requires xprintidle linux package
forceGraceTime = download_wait # time (seconds); in the event that the automatic suspend fails (like locked screen/user is at login screen) The system is given additional grace-time before a suspension is forced.
logFileLocation = "/var/log/Keep.Awake/" # Logfile location
logFileName = "Keep.Awake.log" # Logfile name
# RATIOS
download_waitTOlooptimeRatio = download_wait/looptime
suspend_waitTOlooptimeRatio = suspend_wait/looptime
forceGraceTimeTOlooptimeRatio = forceGraceTime/looptime
# STRING CONSTANTS
key = ["gsettings", "get", "org.gnome.settings-daemon.plugins.power", "sleep-inactive-ac-timeout", "set"]
dbusForceSuspend = ["dbus-send", "--print-reply", "--system", "--dest=org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.UPower.Suspend"]
# WHERE TO OUTPUT
logging.basicConfig(level=logging.INFO, format='%(message)s')
logger = logging.getLogger()
logger.addHandler(logging.FileHandler(logFileLocation + logFileName, 'a'))
print = logger.info
# VARIALBES
rx_speed=0 # receive speed
tx_speed=0 # transmit speed
t = 0 # time interval interation count
countDown = 0 # count down integer
downLoadWaitCountDown = 0 # count down for download_wait
graceCountDown = 0 # count down for forced grace time. See comments above for forceGraceTime CONFIG
graceFlag = False # flag to provide grace period
set_suspend = key[0]+" "+key[-1]+" "+(" ").join(key[2:4])
get_suspend = (" ").join(key[0:4])
force_suspend = (" ").join(dbusForceSuspend)
print ("")
print (">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
print ("KEEP AWAKE v2.1")
print ("Python version: " + (sys.version))
print ("")
print ("Program Date-Time Start: " + datetime.datetime.now().isoformat())
print ("Configuration Loaded...")
print ("suspend_wait: " + str(suspend_wait) + " - Time in seconds for setting 'Suspend when inactive for' for the OS.")
print ("speed_limit: " + str(speed_limit) + " - Minimum amount of data in bytes to qualify as activity.")
print ("looptime: " + str(looptime) + " - Time interval in seconds between checks for network activity.")
print ("download_wait: " + str(download_wait) + " - Time in seconds to wait after last download activity before 'suspend_wait' is applied to the OS.")
print ("userIdle: " + str(userIdle) + " - Idle time in miliseconds to wait before 'suspend_wait' is applied to the OS.")
print ("forceGraceTime: " + str(forceGraceTime) + " - Time in seconds; in the event that the automatic suspend fails (like locked screen/user is at login screen), the system is given additional grace-time before a suspension is forced.")
print ("logFileLocation: " + logFileLocation + " - Logfile location")
print ("logFileName: " + logFileName + " - Logfile name")
print ("")
print ("Variables Loaded...")
print ("rx_speed: " + str(rx_speed) + " - Received bytes in last interval")
print ("tx_speed: " + str(tx_speed) + " - Transmited bytes in last interval")
print ("set_suspend: " + set_suspend + " - String used to construct Shell command to set the 'Suspend when inactive for' for the OS.")
print ("get_suspend: " + get_suspend + " - String used to construct Shell command to get the 'Suspend when inactive for' setting from the OS.")
print ("force_suspend: " + force_suspend + " - String used to construct Shell command to force the 'Suspend.")
print ("\n\n")
def get(cmd):
return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
def get_bytes(t, iface='eth0'):
with open('/sys/class/net/' + iface + '/statistics/' + t + '_bytes', 'r') as f:
data = f.read();
return int(data)
if __name__ == '__main__':
(tx_prev, rx_prev) = (0, 0)
while(True):
print ("Interval Loop Started:\t" + datetime.datetime.now().isoformat())
tx = get_bytes('tx')
rx = get_bytes('rx')
if tx_prev > 0:
tx_speed = tx - tx_prev
if rx_prev > 0:
rx_speed = rx - rx_prev
print (str(tx_speed) + " bytes TRANSMITTED in since last interval.")
print (str(rx_speed) + " bytes RECEIVED in since last interval.")
print ("Starting nap for " + str(looptime) + " seconds...")
time.sleep(looptime)
print ("Awaking from nap:\t" + datetime.datetime.now().isoformat())
tx_prev = tx
rx_prev = rx
speedrx =rx_speed/looptime
print ("RECEIVE speed: " + str(speedrx) + " bytes/second")
speedtx = tx_speed/looptime
print ("TRANSMIT speed: " + str(speedtx) + " bytes/second")
if speedtx > speedrx:
speed = speedtx
else:
speed = speedrx
print ("Highest speed selected: " + str(speed) + " bytes/second")
suspend = get(get_suspend).strip()
print ("Speed Limit configured: " + str(speed_limit) + " bytes/second" )
print ("'t'-value loop counter: " + str(t))
print ("'download_wait'/'looptime': " + str(download_waitTOlooptimeRatio))
print ("'suspend' value == " + suspend)
idleTime = int(get("xprintidle"))
print ("User activity idle time: " + str(idleTime/1000) + " seconds")
print ("User activity idle threshold limit: " + str(userIdle/1000) + " seconds")
if speed > speed_limit or userIdle >= idleTime:
# check/set disable suspend if necessary
if suspend != "0":
subprocess.Popen(["/bin/bash", "-c", set_suspend+" 0"])
t = 0
graceFlag = False
print ("Threshold limits breached... keeping system awake...")
elif t > download_waitTOlooptimeRatio:
# check/enable suspend if necessary
subprocess.Popen(["/bin/bash", "-c", set_suspend+" "+str(suspend_wait)])
countDown = suspend_waitTOlooptimeRatio - (t - download_waitTOlooptimeRatio)
# hack logic - if countDown goes below zero, and automatic sleep fails --> force suspend provide grace period.
if countDown < 0 and not graceFlag:
graceCountDown = -(countDown - forceGraceTimeTOlooptimeRatio)
graceFlag = True
print ("FORCE SUSPEND: Expected automatic sleep did not happen. User desktop session likely locked to login screen.")
print ("FORCE SUSPEND: Providing grace time before forcing suspension.")
print ("FORCE SUSPEND: Counting-down to FORCED suspend..." + str(graceCountDown))
graceCountDown = graceCountDown - 1
elif countDown < 0 and graceFlag:
print ("FORCE SUSPEND: Counting-down to FORCED suspend..." + str(graceCountDown))
graceCountDown = graceCountDown - 1
if graceCountDown < 0:
print ("FORCE SUSPEND: Force Suspending...")
# prime graceFlag to False in case it comes back up to the same conditions allowing a new grace time
graceFlag = False
# execute suspend command
subprocess.call(force_suspend, shell=True)
else:
print ("Cumulative activity below threshold limits... Counting-down to suspend..." + str(countDown))
else:
downLoadWaitCountDown = download_waitTOlooptimeRatio - t
print ("Zero activity... Waiting before setting suspension count down..." + str(downLoadWaitCountDown))
t = t+1
print ("Interval Loop End:\t" + datetime.datetime.now().isoformat())
print ("---------------------------------------------------------")
logrotate configuração personalizada. Use "$ man logrotate" para detalhes de seu uso. É muito útil! ...
FILENAME: "Keep.Awake.v2.logrotate.config"
/var/log/Keep.Awake/Keep.Awake.log
{
copytruncate
size 1M
rotate 30
compress
delaycompress
compresscmd /usr/bin/xz
compressext .xz
compressoptions -9e --threads=0
missingok
notifempty
extension .log
create 664 root danglingpointer
su root root
}