web-dev-qa-db-fra.com

Comment inhiber suspendre temporairement?

J'ai cherché un peu autour de ça et je n'arrive pas à trouver quelque chose d'utile.

Mon ordinateur exécutant Ubuntu 12.10 est configuré pour suspendre ses activités après 30 minutes d'inactivité. Je ne veux pas changer cela, cela fonctionne très bien la plupart du temps.

Ce que je veux faire, c'est désactiver la suspension automatique si une application particulière est en cours d'exécution. Comment puis-je faire ceci?

La chose la plus proche que j'ai trouvée jusqu'ici consiste à ajouter un script Shell dans /usr/lib/pm-utils/sleep.d, qui vérifie si l'application est en cours d'exécution et renvoie 1 pour indiquer qu'il faut empêcher la suspension. Mais , il semble que le système abandonne alors automatiquement la suspension, au lieu de réessayer après 30 minutes supplémentaires. (Autant que je sache, si je déplace la souris, le chronomètre redémarre à nouveau.) Il est fort probable que l'application se terminera au bout de quelques heures et je préférerais que mon PC soit alors automatiquement suspendu si je ne l'utilise pas à ce moment-là . (Je ne souhaite donc pas ajouter d'appel à pm-suspend à la fin de l'application.)

Est-ce possible?

EDIT: Comme je l’ai noté dans l’un des commentaires ci-dessous, ce que je voulais réellement, c’était empêcher la suspension lorsque mon PC servait des fichiers sur NFS; Je voulais juste me concentrer sur la partie "suspension" de la question car j'avais déjà une idée de la façon de résoudre la partie NFS. En utilisant l’idée 'xdotool' donnée dans l’une des réponses, j’ai développé le script suivant, que je lance depuis cron toutes les quelques minutes. Ce n’est pas idéal car cela empêche l’écran de veille de démarrer, mais cela fonctionne. Je dois examiner pourquoi la "caféine" ne réactive pas correctement la suspension plus tard, alors je pourrais probablement faire mieux. Quoi qu'il en soit, cela semble fonctionner, alors je l'inclue ici au cas où quelqu'un d'autre serait intéressé.

#!/bin/bash

# If the output of this function changes between two successive runs of this
# script, we inhibit auto-suspend.
function check_activity()
{
    /usr/sbin/nfsstat --server --list
}

# Prevent the automatic suspend from kicking in. 
function inhibit_suspend()
{
    # Slightly jiggle the mouse pointer about; we do a small step and
    # reverse step to try to stop this being annoying to anyone using the
    # PC. TODO: This isn't ideal, apart from being a bit hacky it stops
    # the screensaver kicking in as well, when all we want is to stop
    # the PC suspending. Can 'caffeine' help?
    export DISPLAY=:0.0
    xdotool mousemove_relative --sync --  1  1
    xdotool mousemove_relative --sync -- -1 -1
}

LOG="$HOME/log/nfs-suspend-blocker.log"
ACTIVITYFILE1="$HOME/tmp/nfs-suspend-blocker.current"
ACTIVITYFILE2="$HOME/tmp/nfs-suspend-blocker.previous"

echo "Started run at $(date)" >> "$LOG"
if [ ! -f "$ACTIVITYFILE1" ]; then
    check_activity > "$ACTIVITYFILE1"
    exit 0;
fi

/bin/mv "$ACTIVITYFILE1" "$ACTIVITYFILE2"
check_activity > "$ACTIVITYFILE1"

if cmp --quiet "$ACTIVITYFILE1" "$ACTIVITYFILE2"; then
    echo "No activity detected since last run" >> "$LOG"
else
    echo "Activity detected since last run; inhibiting suspend" >> "$LOG"
    inhibit_suspend
fi

EDIT 2: Le script ci-dessus fonctionne, mais grâce à un autre commentaire ci-dessous, j’utilise maintenant cette paire de scripts, qui ont l’avantage de permettre à l’économiseur d’écran d’intervenir pendant l’activation de la suspension. Le premier est /usr/lib/pm-utils/sleep.d/000nfs-inhibit, ce qui empêchera une tentative de suspension si un fichier d'inhibition existe:

#!/bin/sh

LOG="/home/zorn/log/nfs-suspend-blocker.log"
INHIBITFILE="/home/zorn/tmp/nfs-suspend-blocker.inhibit"

echo "$0: Started run at $(date), arguments: $*" >> "$LOG"
if [ "$1" = "suspend" ] && [ -f "$INHIBITFILE" ]; then
    echo "$0: Inhibiting suspend" >> "$LOG"
    exit 1
fi
exit 0

La seconde est une version modifiée du script précédent nfs-suspend-blocker et doit toujours être exécutée à partir de cron. Il suit maintenant la stratégie décrite dans le commentaire ci-dessous:

#!/bin/bash

# This works in tandem with /usr/lib/pm-utils/sleep.d/000nfs-inhibit, which
# will prevent a suspend occurring if $INHIBITFILE is present. Once it prevents
# a suspend, it appears that it requires some "user activity" to restart the
# timer which will cause a subsequent suspend attempt, so in addition to
# creating or removing $INHIBITFILE this script also jiggles the mouse after
# removing the file to restart the timer.

# If the output of this function changes between two successive runs of this
# script, we inhibit auto-suspend.
function check_activity()
{
    /usr/sbin/nfsstat --server --list
}

# Slightly jiggle the mouse pointer about; we do a small step and reverse step
# to try to stop this being annoying to anyone using the PC.
function jiggle_mouse()
{
    export DISPLAY=:0.0
    xdotool mousemove_relative --sync --  1  1
    xdotool mousemove_relative --sync -- -1 -1
}

LOG="$HOME/log/nfs-suspend-blocker.log"
ACTIVITYFILE1="$HOME/tmp/nfs-suspend-blocker.current"
ACTIVITYFILE2="$HOME/tmp/nfs-suspend-blocker.previous"
INHIBITFILE="$HOME/tmp/nfs-suspend-blocker.inhibit"

echo "$0: Started run at $(date)" >> "$LOG"
if [ ! -f "$ACTIVITYFILE1" ]; then
    check_activity > "$ACTIVITYFILE1"
    exit 0;
fi

/bin/mv "$ACTIVITYFILE1" "$ACTIVITYFILE2"
check_activity > "$ACTIVITYFILE1"

if cmp --quiet "$ACTIVITYFILE1" "$ACTIVITYFILE2"; then
    echo "$0: No activity detected since last run" >> "$LOG"
    if [ -f "$INHIBITFILE" ]; then
            echo "$0: Removing suspend inhibit file and jiggling mouse" >> "$LOG"
            /bin/rm "$INHIBITFILE"
            jiggle_mouse
    fi
else
    echo "$0: Activity detected since last run; inhibiting suspend" >> "$LOG"
    touch "$INHIBITFILE"
fi
9
Zorn

Un programme pour garder votre ordinateur éveillé est Caféine . Je ferais un fichier .bash_aliases pour appeler également la caféine lorsque votre code d'origine est appelé.

alias newname="origcode && caffeine"

Selon le code pour lequel vous essayez de maintenir votre ordinateur en état de veille, vous devrez créer un script personnalisé incluant la suppression de la caféine lorsque l'autre code est arrêté. Quelques détails supplémentaires sur le code particulier pourraient aider.

Mise à jour: Un moyen plus simple serait de lancer xdotool , qui peut être installé avec Sudo apt-get install xdotool. Vous pouvez écrire un script appelé à l'ouverture de votre code cible, puis utiliser la commande sleep pendant 29 minutes, puis exécuter xdotool key a ou utiliser un moyen quelconque pour maintenir l'ordinateur en état de veille.

7
philshem

Si

  1. Un script dans /usr/lib/pm-utils/sleep.d peut vérifier si l'application est en cours d'exécution et renvoyer 1 pour indiquer que la suspension doit être empêchée.
  2. Le problème de "le système cesse alors de suspendre automatiquement, au lieu d'essayer de nouveau après 30 minutes" est résolu en déplaçant la souris qui redémarre le chronomètre (j'espère avoir bien compris ce que vous entendez par là).

alors pourquoi ne pas simplement déplacer le pointeur de la souris après la fin de l’application.

Pour résumer:

  1. Utilisez sleep.d pour empêcher le système de suspendre.
  2. Ecrivez un script qui bouge la souris une fois.
  3. Appelez 'Long-running-script && mousejiggle'

Cela n'empêchera pas l'économiseur d'écran.

Le seul problème est qu'il s'écoulera 30 minutes après la fin du processus lorsque le système sera suspendu. C'est le cas de votre solution 'EDIT' également.

PS: Je cherchais une solution à un problème similaire lorsque j'ai découvert xdotool sur cette page. Donc merci. J'espère que cela t'aides.

5
S Prasanth

Bien que EDIT 2 permette à l’économiseur d’écran de reprendre ses activités et de reprendre le service d’autosuspend lors de la suppression du fichier d’inhibition, comme indiqué ci-dessus, le système sera suspendu 30 minutes après la suppression du fichier.

Une solution possible consiste à désactiver l'économiseur d'écran intégré et les fonctionnalités de suspension automatique, à les implémenter nous-mêmes et à choisir le comportement du minuteur en fonction des besoins. La commande xprintidle (vous devrez peut-être l'installer) affiche le nombre de millisecondes pendant lequel aucune activité du clavier ou de la souris n'a été effectuée. Cela ouvre plusieurs possibilités. J'ai implémenté le gestionnaire d'inactivité suivant dans python (pas trop d'un script bash). Les fonctions incluent la définition de la commande, du délai d’expiration et du fichier d’inhibition (je l’ai appelé verrouiller) pour l’économiseur d’écran et/ou la suspension automatique. De plus, il est possible de choisir si le minuteur d'inactivité doit redémarrer lorsque le fichier d'inhibition est supprimé ou non (le comportement peut être différent pour la suspension et l'économiseur d'écran). J'ai essayé de préciser l'utilisation dans les notes, mais si quelque chose n'est pas clair, demandez-le.

#!/usr/bin/python

#Notes:##################

#   1. All TIMEOUTs are specified in seconds
#   2. 0 or negative TIMEOUT disables a particular action.
#   3. If an actionCOMMAND (like pm-suspend) requires 'Sudo'ing, make them 'Sudo'able without password. Alternatively, you may run this script in Sudo mode, and make this script sudoable without password. https://askubuntu.com/questions/159007/specific-Sudo-commands-without-password
#   4. 'action'_timer_starts_... option: True - if a lock file is created and then removed, inactivity timer (for that action) restarts at the time of deletion of lock. False - doesn't restart.
#   5. screensaverCOMMAND can be screen-lock (security) or screen-off (power saving) or both. To do both, but at different times (I can't see any reason to do so) extend this script from two actions (screensaver, autosuspend) to three (screen-lock, screen-off, autosuspend).

#########################

import os
import time
import threading
import subprocess

HOME = os.getenv('HOME') + '/'

#Configuration###########

screensaverCOMMAND = "gnome-screensaver-command --lock && xset -display :0.0 +dpms dpms force off"
autosuspendCOMMAND = "gnome-screensaver-command --lock && Sudo pm-suspend"

screensaverTIMEOUT = 10*60
autosuspendTIMEOUT = 20*60

screensaverLOCK = HOME + ".inactivitymanager/screensaverLOCK"
autosuspendLOCK = HOME + ".inactivitymanager/autosuspendLOCK"

screensaver_timer_starts_only_after_lockfile_is_deleted = False
autosuspend_timer_starts_only_after_lockfile_is_deleted = False

#########################

def stayOn():
    print "inactivitymanager is running..."
    try:
        while True:
            time.sleep(10)
    except:
        print "Closed."

class inactivity_action(threading.Thread):
    def __init__(self, command, timeout, lock, timer_starts_blah):
        threading.Thread.__init__(self)
        self.daemon = True
        self.command = command
        self.timeout = timeout
        self.lock = lock
        self.timer_starts_blah = timer_starts_blah
    def run(self):
        if not(self.timer_starts_blah):
            while True:
                try:
                    while True:
                        time.sleep(1)
                        f = open(self.lock, 'r')
                        f.close()
                except IOError:
                    xidletime = int(subprocess.Popen('xprintidle', stdout = subprocess.PIPE).communicate()[0])/1000
                    if xidletime > self.timeout:
                        os.system(self.command)
                    else:
                        time.sleep(self.timeout - xidletime + 2)
        else:
            lockremovetime = 0
            while True:
                lockdetected = False
                try:
                    while True:
                        time.sleep(1)
                        f = open(self.lock, 'r')
                        f.close()
                        lockdetected = True
                except IOError: #Will enter this section if/when lockfile is/becomes absent
                    xidletime = int(subprocess.Popen('xprintidle', stdout = subprocess.PIPE).communicate()[0])/1000
                    if lockdetected:
                        lockremovetime = int(time.time())
                    timesincelockremove = int(time.time()) - lockremovetime
                    if min(xidletime, timesincelockremove) > self.timeout:
                        os.system(self.command)

if screensaverTIMEOUT > 0:
    inactivity_screensaver = inactivity_action(screensaverCOMMAND, screensaverTIMEOUT, screensaverLOCK, screensaver_timer_starts_only_after_lockfile_is_deleted)
    inactivity_screensaver.start()

if autosuspendTIMEOUT > 0:
    inactivity_autosuspend = inactivity_action(autosuspendCOMMAND, autosuspendTIMEOUT, autosuspendLOCK, autosuspend_timer_starts_only_after_lockfile_is_deleted)
    inactivity_autosuspend.start()

stayOn()

Usage:

  1. Ajoutez simplement inactivitymanager & à .profile ou .xsessionrc dans le répertoire de base (voyez lequel fonctionne pour vous. N'ajoutez pas dans les deux, sinon deux instances de ce script s'exécutent simultanément, quelque chose que je n'ai pas encore géré. Je suppose c’est dans ces détails que les principales implémentations prévalent sur les implémentations personnalisées).
  2. Vous devrez peut-être installer xprintidle.

La façon dont le fichier inhibit y parvient est laissée à l’imagination de l’utilisateur pour le moment (si je me propose d’implémenter un démon pour cela, je le mettrai dans un EDIT pour cette réponse). Vous (OP) l'avez bien sûr résolu pour votre cas. Un écueil à éviter lors de la tentative d'interdiction de la suspension pour plusieurs processus est la suppression du fichier de verrouillage lorsqu'un processus se termine tandis qu'un autre est en cours d'exécution. Alternativement, le script peut être légèrement modifié pour empêcher la suspension si un fichier existe dans un répertoire particulier (un répertoire verrouillé). De cette façon, chaque processus peut avoir son propre fichier de verrouillage.

Remarques:

  1. Ce script est assez léger sur le processeur et la mémoire. Mais supprimer le time.sleep (1) dans le code peut causer des problèmes - pas encore vérifié.
  2. pm-suspend nécessite des autorisations Sudo. Pour suspendre pm sans donner de vérification du mot de passe Comment exécuter des commandes Sudo spécifiques sans mot de passe? . Sinon, vous pouvez exécuter ce script en mode Sudo et le rendre compatible avec un mot de passe sans problème (pas de problème si vous exécutez le script en tant que root).
  3. Le script peut rencontrer des problèmes si les délais d'attente sont définis pour être inférieurs à ~ 10 secondes (je ne vérifie pas exactement où le problème commence doit être inférieur à 5, je suppose). Cela peut être géré en supprimant quelques time.sleep (1) aux dépens des ressources du système. Ne pensez pas que quiconque en aura besoin.
  4. Parce que nous avons une poignée sur les minuteries, pas besoin de changer la souris!
1
S Prasanth