¿Cómo inhibir suspender temporalmente?

10

He buscado un poco por esto y parece que no puedo encontrar nada útil.

Tengo mi PC con Ubuntu 12.10 configurado para suspender después de 30 minutos de inactividad. No quiero cambiar eso, funciona muy bien la mayor parte del tiempo.

Lo que sí quiero hacer es desactivar la suspensión automática si se está ejecutando una aplicación en particular. ¿Cómo puedo hacer esto?

Lo más cercano que he encontrado hasta ahora es agregar un script de shell en el /usr/lib/pm-utils/sleep.dque verifica si la aplicación se está ejecutando y devuelve 1 para indicar que se debe evitar la suspensión. Pero parece que el sistema abandona la suspensión automática, en lugar de intentarlo nuevamente después de otros 30 minutos. (Por lo que puedo decir, si muevo el mouse, eso reinicia el temporizador nuevamente.) Es muy probable que la aplicación termine después de un par de horas, y prefiero que mi PC se suspenda automáticamente si no estoy usando en ese punto . (Por lo tanto, no quiero agregar una llamada a pm-suspend cuando finalice la aplicación).

es posible?

EDITAR: Como señalé en uno de los comentarios a continuación, lo que realmente quería era inhibir la suspensión cuando mi PC estaba sirviendo archivos a través de NFS; Solo quería centrarme en la parte "suspender" de la pregunta porque ya tenía una idea de cómo resolver la parte NFS. Utilizando la idea 'xdotool' dada en una de las respuestas, se me ocurrió el siguiente script que ejecuto desde cron cada pocos minutos. No es ideal porque también detiene el protector de pantalla, pero funciona. Necesito echar un vistazo a por qué la 'cafeína' no vuelve a habilitar correctamente la suspensión más adelante, entonces probablemente podría hacerlo mejor. De todos modos, esto parece funcionar, así que lo incluyo aquí en caso de que alguien más esté interesado.

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

EDITAR 2: el script anterior funciona, pero gracias a otro comentario a continuación, ahora estoy usando este par de scripts, que tienen la ventaja de permitir que el protector de pantalla se active mientras inhibo la suspensión. El primero es /usr/lib/pm-utils/sleep.d/000nfs-inhibit, que evitará un intento de suspensión si existe un archivo de inhibición:

#!/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 segunda es una versión modificada del script nfs-suspend-blocker anterior y aún debe ejecutarse desde cron. Ahora sigue la estrategia descrita en el comentario a continuación:

#!/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
Zorn
fuente
En lugar de desordenar la pregunta, debe poner sus dos soluciones al problema como respuesta a continuación.
Cas

Respuestas:

8

Un programa para mantener su computadora despierta es la cafeína . Haría un archivo .bash_aliases para llamar también cafeína cuando se llama a su código original.

alias newname="origcode && caffeine"

Dependiendo del código que intente mantener su computadora despierta, tendrá que crear un script personalizado que incluya matar la cafeína cuando se detenga el otro código. Algunos detalles más sobre el código particular ayudarían.

Actualización: una forma más sencilla sería ejecutar xdotool , que se puede instalar con sudo apt-get install xdotool. Puede escribir una secuencia de comandos que se llama cuando se abre el código de destino y luego usar el sleepcomando durante 29 minutos y luego ejecutar xdotool key ao algo arbitrario para mantener la computadora despierta.

philshem
fuente
2
Para xdo, probablemente sea mejor elegir una clave que no haga algo inherentemente. Al presionar Mayús, por ejemplo, se activará la pantalla sin escribir en la ventana activa.
Oli
1
Gracias. Estaba ocultando deliberadamente un poco de detalle en la pregunta original: lo que quiero hacer explícitamente es detener la suspensión de mi PC (que sirve contenido multimedia a través de NFS) mientras mi centro de medios está accediendo a ella. Si conoce una manera específica de abordar esto que sería genial, de lo contrario, puedo ver un par de vías que permitirán que esto funcione a través de cafeína (por ejemplo, el centro de medios ingresará a mi PC cada 10 minutos y ejecutará un script de shell que duerme durante 15 minutos).
Zorn
1
He probado Caffeine y parece funcionar, excepto que una vez que el programa en ejecución desaparece, la salida de Caffeine dice que suspender ya no se inhibe, pero lo dejé por el doble del período de inactividad y aunque la pantalla suspendió la PC nunca lo hizo. Seguiré jugando con esto aún más, aunque la ruta xdo probablemente será aún más conveniente y lo intentaré primero. PD ¿Hay alguna forma de insertar una nueva línea en un comentario?
Zorn
5

Si

  1. Un script en /usr/lib/pm-utils/sleep.d puede verificar si la aplicación se está ejecutando y devolver 1 para indicar que se debe evitar la suspensión.
  2. El problema de "el sistema abandona la suspensión automática, en lugar de volver a intentarlo después de otros 30 minutos" se resuelve moviendo el mouse que reinicia el temporizador nuevamente (espero haber entendido bien lo que quiere decir con esto)

entonces, ¿por qué no simplemente agitar el puntero del mouse una vez que finaliza la aplicación?

Resumir:

  1. Use sleep.d para evitar que el sistema se suspenda.
  2. Escribe una secuencia de comandos que mueva el mouse una vez.
  3. Llame 'Long-running-script && mousejiggle'

Esto no obstaculizará el protector de pantalla.

El único problema es que serán 30 minutos después de que el proceso finalice cuando el sistema se suspenda. Este es el caso con su solución 'EDITAR' también.

PD: Estaba buscando una solución a un problema similar cuando supe de xdotool en esta página. Así que gracias. Espero que esto ayude.

S Prasanth
fuente
Ingenioso, gracias! Lo intentaré este fin de semana.
Zorn
La pista sobre la pm-utilsayuda ayudó. Tenga en cuenta que el paquete pm-utilsdebe instalarse para que esto funcione: el directorio en sí puede existir incluso si el paquete no está instalado.
krlmlr
1

Aunque EDIT 2 permite que se active el protector de pantalla y reanuda el servicio de suspensión automática al eliminar el archivo de inhibición, como se indicó anteriormente, serán 30 minutos después de que se elimine el archivo cuando el sistema se suspenda.

Una posible solución es deshabilitar el protector de pantalla incorporado y la funcionalidad de suspensión automática e implementarlos por nuestra cuenta, y elegir el comportamiento del temporizador según sea necesario. El comando xprintidle(puede que tenga que instalar esto) imprime el número de milisegundos para los que no ha habido actividad de teclado o mouse. Esto abre varias posibilidades. He implementado el siguiente administrador de inactividad en python (no demasiado de un scripter bash). Las características incluyen la configuración del comando, el tiempo de espera y el archivo de inhibición (lo he llamado bloqueo) para el protector de pantalla y / o la suspensión automática. Además, existe la opción de elegir si el temporizador de inactividad debe reiniciarse cuando se elimina o no el archivo de inhibición (el comportamiento puede ser diferente para la suspensión y el protector de pantalla). He tratado de aclarar el uso en las notas, pero si algo no está claro, pregunte.

#!/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. /ubuntu/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()

Uso:

  1. Simplemente agregue inactivitymanager &a .profile o .xsessionrc en el directorio de inicio (vea cuál funciona para usted. No agregue ambos, de lo contrario, dos instancias de este script se ejecutarán simultáneamente, algo que no he manejado. Supongo que está en estos detalles que las implementaciones convencionales prevalecen sobre las personalizadas).
  2. Puede que tenga que instalar xprintidle.

La forma en que el archivo de inhibición llega allí queda a la imaginación del usuario por ahora (si me atrevo a implementar un demonio para esto, lo pondré en un EDITAR para esta respuesta). Usted (OP), por supuesto, lo ha resuelto para su caso. Un obstáculo que debe evitarse cuando se intenta inhibir la suspensión de más de un proceso es eliminar el archivo de bloqueo cuando un proceso finaliza mientras otro se está ejecutando. Alternativamente, el script puede editarse ligeramente para inhibir la suspensión si existe algún archivo en un directorio particular (un directorio de bloqueo). De esta manera, cada proceso puede tener su propio archivo de bloqueo.

Notas:

  1. Este script es bastante ligero en el procesador y la memoria. Pero eliminar los time.sleep (1) s en el código puede causar problemas, aunque no lo he verificado.
  2. pm-suspend requiere permisos de sudo. Para suspender por la tarde sin dar contraseña de pago ¿Cómo ejecuto comandos sudo específicos sin contraseña? . Alternativamente, puede ejecutar este script en modo sudo y hacer que este script sea sudoable sin contraseña (no es un problema si ejecuta script como root)
  3. El script podría tener problemas si los tiempos de espera se configuran en menos de ~ 10 segundos (no creo que el inicio exacto del problema sea menor de 5, supongo). Esto puede manejarse eliminando algunos time.sleep (1) s a expensas de los recursos del sistema. Sin embargo, no creo que nadie necesite esto.
  4. Debido a que tenemos un control de los temporizadores, ¡no se requieren jiggles de mouse!
S Prasanth
fuente