Existe alguma maneira de fazer o Ubuntu não suspender enquanto um download está em andamento?

4

Existe alguma maneira?

Como criar um script em /usr/lib/pm-utils/sleep.d para verificar ${downspeed eth0} , ${upspeed wlan0} , ${upspeed eth0} e ${downspeed wlan0} e configurar o sistema para não suspender enquanto um download estiver em andamento, mas apenas desativar a tela?

Meu sistema operacional é o Ubuntu 15.04.

    
por dhiya 22.01.2015 / 13:05

3 respostas

7

Inspirado no segundo comentário do @ByteCommanders, o script abaixo faz o que você descreve: assumindo que a pasta de downloads é o diretório do qual você faz o download , desativa a suspensão durante o download e espera por cinco minutos para definir) antes de reativar a suspensão, para garantir que o download esteja realmente terminado.
Você pode definir qualquer outro diretório para ser visto como pasta de download.

Como funciona

Em um loop (uma vez por 20 segundos), o script verifica o tamanho da pasta de destino com o comando:

du -ks ~/Downloads

O script compara cada verificação com a última, para verificar se há atividade de download (aumento do tamanho). Se não houver atividade por mais de cinco minutos (mas você pode definir qualquer outro tempo de espera), o script presume que nenhum download está ocorrendo e a suspensão "normal" está (reativada).

Por outro lado: se o script perceber o aumento do tamanho do diretório ~/Downloads , ele desativará a suspensão, até que nenhuma atividade seja detectada por mais de cinco minutos.

Baixo em suco

Os comandos do script são extremamente baixos em recursos. Como o ciclo é executado apenas uma vez por 20 segundos (como está), a carga do processador é praticamente nula.

O script

#!/usr/bin/env python3
import subprocess
import time

#--- set suspend time below (seconds)
suspend_wait = 300
#---

#--- you can change values below, but I'd leave them as they are
speed_limit = 0      # set a minimum speed (kb/sec) to be considered a download activity
looptime = 20        # time interval between checks
download_wait = 300  # time (seconds) to wait after the last download activity before suspend is re- activated
#---

t = 0
key = ["gsettings", "get", "org.gnome.settings-daemon.plugins.power", "sleep-inactive-ac-timeout", "set"]

set_suspend = key[0]+" "+key[-1]+" "+(" ").join(key[2:4])
get_suspend = (" ").join(key[0:4])

def get_size():
    return int(subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8").split()[0])

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")

check_1 = int(get("du -ks ~/Downloads").split()[0])

while True:
    time.sleep(looptime)
    try:
        check_2 = int(get("du -ks ~/Downloads").split()[0])
    except subprocess.CalledProcessError:
        pass
    speed = int((check_2 - check_1)/looptime)
    # check current suspend setting
    suspend = get(get_suspend).strip()
    if speed > speed_limit:
        # check/set disable suspend if necessary
        if suspend != "0":
            subprocess.Popen(["/bin/bash", "-c", set_suspend+" 0"])
        t = 0
    else:
        if all([t > download_wait/looptime, suspend != str(download_wait)]):
            # check/enable suspend if necessary
            subprocess.Popen(["/bin/bash", "-c", set_suspend+" "+str(suspend_wait)])
    check_1 = check_2
    t = t+1

Como usar

  1. Copie o script abaixo em um arquivo vazio, salve-o como no_suspend.py
  2. Na seção head do script, defina o tempo de suspensão "normal" desejado (já que o script reativará a suspensão):

    #--- set suspend time below (seconds)
    suspend_wait = 300
    #---
    
  3. Se você quiser, você pode definir outros valores:

    #--- you can change values below, but I'd leave them as they are
    speed_limit = 0      # set a minimum speed (kb/sec) to be considered a download activity
    looptime = 20        # time interval between checks
    download_wait = 300  # time (seconds) to wait after the last download activity before suspend is re- activated
    #---
    
  4. Teste- execute o script com o comando:

    python3 /path/to/no_suspend.py
    
  5. Se tudo funcionar bem, adicione-o aos seus aplicativos de inicialização: Dash > Aplicativos de inicialização > adicione o comando:

    python3 /path/to/no_suspend.py
    
por Jacob Vlijm 11.08.2015 / 21:11
4

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

  1. Tráfego de rede
  2. Atividade do usuário
  3. 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 ...

  1. Verifica a atividade do usuário e o tráfego de rede com base nos limites
  2. Se um ou ambos estiverem acima dos limites, as configurações de energia de suspensão do sistema operacional serão desativadas.
  3. 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
  4. Implementou uma impressão que vai para um arquivo de log e uma saída padrão usando os recursos do python 3.
  5. Adicionadas muitas impressões de dados para determinar o estado. Muito útil para solucionar problemas.
  6. Na lógica If-elif-else, adicionei contadores de contagem regressiva.
  7. Adicionamos muitos comentários, e esperamos que ajudem aqueles que são novatos em tudo isso.
  8. 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)
  9. É altamente recomendado que o cron logrotate seja movido para cron.hourly
  10. Faz uso de xprintidle
  11. logrotate config faz uso do xz-utils
  12. 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.
  13. 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.
  14. 16/09/2015 - versão 2.1 - Adicionado a lógica do Force Graceful Suspension
  15. 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
    }
    
por DanglingPointer 12.09.2015 / 18:33
3

Com base na resposta fornecida aqui , modifiquei @ De Jacob Vlijm script da seguinte maneira, para evitar que o Ubuntu suspenda enquanto qualquer upload ou download estiver em andamento. Você precisa instalar o xprintidle primeiro.

#!/usr/bin/env python3
#install xprintidle first, it is a binary written in C; see  https://packages.debian.org/sid/xprintidle 
#This script is for prevent/supersede suspend while a download/upload in progress.
#Change wlan0 (wifi) to eth0 (ethernet) or use both if its applies. 
#add it to your startup applications: Dash > Startup Applications > add the command: python3 /path/to/delay_suspend.py
import subprocess
import time
time.sleep(15)
subprocess.Popen(['notify-send', "Ubuntu will supersede suspend while a download/upload in progress"])    

#--- set suspend time below (seconds)
suspend_wait = 300
#---

#--- you can change values below, but I'd leave them as they are
speed_limit = 1000      # set a minimum speed (bytes/looptime) to be considered a download activity
looptime = 20       # time interval between checks
download_wait = 300  # time (seconds) to wait after the last download activity before suspend is re- activated
#---

rx_speed=0
tx_speed=0
speed=0
idletime = 2

t = 0
key = ["gsettings", "get", "org.gnome.settings-daemon.plugins.power", "sleep-inactive-ac-timeout", "set"]

set_suspend = key[0]+" "+key[-1]+" "+(" ").join(key[2:4])
get_suspend = (" ").join(key[0:4])

def get_size():
    return int(subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8").split()[0])

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")



def get_bytes(t, iface='wlan0'):
    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)
#Rx stand for received (download) and Tx for tranferred (upload).
    while(True):
        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


        time.sleep(looptime)

        tx_prev = tx
        rx_prev = rx

        speedrx =rx_speed/looptime
        #print('RX: ', rx_speed, 'xxxxx')
        speedtx = tx_speed/looptime
        if speedtx > speedrx:
            speed = speedtx
        else:
            speed = speedrx


    # check current suspend setting
        suspend = get(get_suspend).strip()
        idletime = float(subprocess.check_output('xprintidle').strip())
        idletime=idletime/1000
        if speed > speed_limit:
            # check/set disable suspend if necessary
            if suspend != "0":
                subprocess.Popen(["/bin/bash", "-c", set_suspend+" 0"])

            if idletime >  download_wait-2*looptime:
                subprocess.Popen(['notify-send', "Postponed suspend due to active net traffic"]) 
                    #subprocess.Popen(['notify-send', str(speed) +"Postponed suspend for completion of active upload/download"+ str(speed_limit)])  
            t = 0
        else:
            if all([t > download_wait/looptime, suspend != str(download_wait)]):
                # check/enable suspend if necessary
                subprocess.Popen(["/bin/bash", "-c", set_suspend+" "+str(suspend_wait)])

        t = t+1
        #print(idletime)
        #print(speed)
        #print(speed_limit)        
        #subprocess.Popen(['notify-send', str(idletime)])
        #print('speed:', speed)
        #print('speed limit:', speed_limit)
    
por dhiya 13.08.2015 / 20:29