web-dev-qa-db-fra.com

Existe-t-il un moyen de faire en sorte qu'Ubuntu ne suspende pas le téléchargement en cours?

Y a-t-il un moyen?

Comment créer un script dans /usr/lib/pm-utils/sleep.d pour vérifier ${downspeed eth0}, ${upspeed wlan0}, ${upspeed eth0} et ${downspeed wlan0} et pour que le système ne soit pas suspendu tant qu'un téléchargement est en cours, mais seulement filtrer?

Mon système d'exploitation est Ubuntu 15.04.

4
dhiya

Inspiré par le second commentaire de @ByteCommanders, le script ci-dessous fait ce que vous décrivez: en supposant que le dossier de téléchargement est le répertoire dans lequel vous téléchargez, il désactive la suspension pendant le téléchargement et attend ensuite pendant cinq minutes (à définir de manière arbitraire) avant de réactiver la suspension, pour vous assurer que le téléchargement est vraiment terminé.
Vous pouvez définir tout autre répertoire à regarder comme dossier de téléchargement.

Comment ça fonctionne

Dans une boucle (une fois toutes les 20 secondes), le script vérifie la taille du dossier cible à l'aide de la commande:

du -ks ~/Downloads

Le script compare chaque vérification à la dernière pour vérifier l'activité de téléchargement (augmentation de la taille). S'il n'y a aucune activité pendant plus de cinq minutes (mais vous pouvez définir un autre délai d'attente), le script suppose qu'aucun téléchargement n'est en cours et que la suspension "normale" est (ré) activée.

Inversement: si le script voit la taille du répertoire ~/Downloads augmenter, il désactive la suspension jusqu'à ce qu'aucune activité ne soit détectée pendant plus de cinq minutes.

Peu de jus

Les commandes du script sont extrêmement limitées en ressources. Étant donné que le cycle ne s'exécute qu'une fois toutes les 20 secondes (en l'état), la charge du processeur est pratiquement nulle.

Le scénario

#!/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

Comment utiliser

  1. Copiez le script ci-dessous dans un fichier vide, enregistrez-le sous le nom no_suspend.py
  2. Dans la section head du script, définissez le délai de suspension "normal" souhaité (car le script réactivera la suspension):

    #--- set suspend time below (seconds)
    suspend_wait = 300
    #---
    
  3. Si vous voulez, vous pouvez définir d'autres valeurs:

    #--- 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. Test - lancez le script avec la commande:

    python3 /path/to/no_suspend.py
    
  5. Si tout fonctionne correctement, ajoutez-le à vos applications de démarrage: Dash> Applications de démarrage> ajoutez la commande:

    python3 /path/to/no_suspend.py
    
7
Jacob Vlijm

UPDATE (2016-06-11) : Depuis que le script a été écrit pour la première fois, il est devenu un programme complet qui détermine le moment de la suspension en fonction

  1. Trafic réseau
  2. Activité de l'utilisateur
  3. Charge du processeur

Je l'ai publié sur Launchpad ici https://launchpad.net/keep.awake sous une licence GPL.

Il n'y a pas encore de paquet snap ou deb, mais j'y reviendrai par la suite. En attendant, vous pouvez télécharger this et le décompresser.

Cela fonctionne comme une commande appropriée.
Tapez - aidez-nous à voir une liste complète de ce qui peut être fait. Les exemples ci-dessous ne sont que quelques-uns:
./keepawake.py --help

Pour s'exécuter de manière interactive:
./keepawake.py

Pour exécuter en tant que service en arrière-plan:
Nohup ./keepawake.py -r > /dev/null 2>&1 &

Pour exécuter le service d’arrière-plan et définir 15 minutes (900 secondes) comme durée d’inactivité de l’activité utilisateur avant de déterminer que l’utilisateur est inactif:
Nohup ./keepawake.py -u 900 -r > /dev/null 2>&1 &

Pour exécuter le service d’arrière-plan et définir la charge minimale du processeur sur 13%:
Nohup ./keepawake.py -c 13 -r > /dev/null 2>&1 &

Pour exécuter le service d’arrière-plan et définir le trafic réseau minimal sur 5 Ko (5 120 octets):
Nohup ./keepawake.py -s 5120 -r > /dev/null 2>&1 &

Pour exécuter les trois paramètres ci-dessus (réseau, CPU, utilisateur inactif) en une fois:

Nohup ./keepawake.py -s 5120 -c 13 -u 900 -r > /dev/null 2>&1 &


[POST ORIGINAL] :

Sur la base de la réponse de Dhiya, j'ai fortement modifié le script. Il gère à la fois le trafic réseau ET l'activité de l'utilisateur !

Je devais lui donner un nom alors je l'ai nommé "Keep Awake".

Essayez-le et répondez si vous avez des questions ou des commentaires!

Notes de version ...

  1. Vérifie à la fois l'activité des utilisateurs et le trafic réseau en fonction de seuils
  2. Si l'un ou les deux dépassent les limites, les paramètres de mise en veille du système d'exploitation sont désactivés.
  3. Ma première modification du code l'a ramené à Python 2.7.x. J'ai dû le migrer à 3.4.x.
  4. Implémentation d'une impression qui va à la fois vers un fichier journal et une sortie standard à l'aide des fonctionnalités python 3.
  5. Ajout de nombreuses impressions de données pour déterminer l'état. Très utile pour le dépannage.
  6. Dans la logique If-Elif-else, j'ai ajouté des comptes à rebours.
  7. Ajout de nombreux commentaires, j'espère aider les nouveaux à tout cela.
  8. Vous avez fourni une configuration logrotate que vous pouvez utiliser pour gérer indéfiniment les journaux de sortie. (Voir les commentaires dans l'historique)
  9. Il est fortement recommandé de déplacer le logrotate cron vers cron.hourly
  10. Utilise xprintidle
  11. logrotate config utilise xz-utils
  12. Des tests de performance répétés ont montré que l’impact du processeur est pratiquement négligeable. Seul l'algorithme de compression xz exécuté par logrotate peut affecter un seul cœur jusqu'à 100%. Mais il ne dure pas longtemps sur les processeurs modernes, plus il est simple thread. Ainsi, vos autres noyaux peuvent effectuer un autre travail. Il ne compressera que les journaux vieux de quelques jours ou supérieurs à 20 Mo.
  13. Une fois que vous êtes satisfait de la configuration, vous pouvez la configurer à l'aide du lanceur intégré de la distribution, qui lancera le programme lors de la connexion à votre compte. Assurez-vous que logrotate est configuré avec la configuration de script ci-dessous pour gérer les fichiers journaux. Vous pouvez également modifier cela à votre guise.
  14. 16/09/2015 - version 2.1 - Ajout de la logique Force Graceful Suspension
  15. 16/09/2015 - version 2.1 - Le programme est maintenant conçu pour fonctionner avec les privilèges Sudo et se connecter à /var/log/Keep.Awake/. logrotate config passera désormais par défaut au traitement multicœur pour la compression et ne effectuera une rotation que si elle est supérieure à 1M. Cela nécessite xz-utils> = v5.2.0

Exemple de commande à exécuter en arrière-plan

    $ Sudo Nohup python3 Keep\ Awake.v2.py > /dev/null 2>&1 &

FILENAME: "Conserver\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://askubuntu.com/questions/576525/can-i-prevent-ubuntu-being-suspended-while-a-download-is-in-progress/661085#661085
    # 2015-09-12    DanglingPointer - Modified to version 2 and renamed "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 __== '__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 config personnalisé Utilisez "$ man logrotate" pour plus de détails sur son utilisation. C'est très pratique! ... 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
    }
4
DanglingPointer

Sur la base de la réponse fournie ici , j'ai modifié le script script de @Jobob Vlijm comme suit, afin d'empêcher Ubuntu de suspendre ses activités pendant le téléchargement. Vous devez installer xprintidle en premier.

#!/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 __== '__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)
3
dhiya