Wie kann man das Suspendieren vorübergehend verhindern?

10

Ich habe ein bisschen danach gesucht und kann anscheinend nichts hilfreiches finden.

Ich habe meinen PC mit Ubuntu 12.10 so eingerichtet, dass er nach 30 Minuten Inaktivität angehalten wird. Ich möchte das nicht ändern, es funktioniert die meiste Zeit großartig.

Ich möchte das automatische Anhalten deaktivieren, wenn eine bestimmte Anwendung ausgeführt wird. Wie kann ich das machen?

Das Nächste, was ich bisher gefunden habe, ist das Hinzufügen eines Shell-Skripts, in /usr/lib/pm-utils/sleep.ddem überprüft wird, ob die Anwendung ausgeführt wird, und 1 zurückgegeben wird, um anzugeben, dass das Anhalten verhindert werden soll. Es sieht jedoch so aus, als würde das System das automatische Anhalten aufgeben, anstatt es nach weiteren 30 Minuten erneut zu versuchen. (Soweit ich das beurteilen kann, startet der Timer beim Bewegen der Maus erneut.) Es ist sehr wahrscheinlich, dass die Anwendung nach ein paar Stunden beendet wird. Ich möchte lieber, dass mein PC automatisch angehalten wird, wenn ich ihn nicht verwende es an diesem Punkt . (Daher möchte ich pm-suspend nach Abschluss der Anwendung nicht mehr aufrufen.)

Ist das möglich?

BEARBEITEN: Wie ich in einem der folgenden Kommentare festgestellt habe, wollte ich eigentlich das Suspendieren verhindern, wenn mein PC Dateien über NFS bereitstellt. Ich wollte mich nur auf den "Suspend" -Teil der Frage konzentrieren, da ich bereits eine Idee hatte, wie der NFS-Teil gelöst werden kann. Unter Verwendung der in einer der Antworten angegebenen 'xdotool'-Idee habe ich das folgende Skript erstellt, das ich alle paar Minuten von cron aus starte. Es ist nicht ideal, weil es den Bildschirmschoner ebenfalls davon abhält, einzuschalten, aber es funktioniert. Ich muss einen Blick darauf werfen, warum 'Koffein' das Suspendieren später nicht richtig wieder aktiviert, dann könnte ich es wahrscheinlich besser machen. Wie auch immer, das scheint zu funktionieren, also füge ich es hier ein, falls jemand anderes interessiert ist.

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

BEARBEITEN 2: Das obige Skript funktioniert, aber dank eines weiteren Kommentars unten verwende ich jetzt dieses Skriptpaar, das den Vorteil hat, dass der Bildschirmschoner aktiviert werden kann, während ich das Suspendieren hemme. Das erste ist /usr/lib/pm-utils/sleep.d/000nfs-inhibit, wodurch ein Suspendierungsversuch verhindert wird, wenn eine Sperrdatei vorhanden ist:

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

Die zweite ist eine modifizierte Version des vorherigen nfs-suspend-blocker-Skripts und sollte weiterhin von cron ausgeführt werden. Es folgt nun der im Kommentar unten beschriebenen Strategie:

#!/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
quelle
Anstatt die Frage zu überladen, sollten Sie Ihre beiden Lösungen für das Problem als Antwort unten angeben.
Cas

Antworten:

8

Ein Programm, um Ihren Computer wach zu halten, ist Koffein . Ich würde eine .bash_aliases-Datei erstellen, um auch Koffein aufzurufen, wenn Ihr ursprünglicher Code aufgerufen wird.

alias newname="origcode && caffeine"

Abhängig davon, für welchen Code Sie Ihren Computer wach halten möchten, müssen Sie ein benutzerdefiniertes Skript erstellen, das das Abtöten von Koffein umfasst, wenn der andere Code gestoppt wird. Einige weitere Details zum jeweiligen Code würden helfen.

Update: Eine einfachere Möglichkeit wäre, xdotool auszuführen , mit dem installiert werden kann sudo apt-get install xdotool. Sie können ein Skript schreiben, das aufgerufen wird, wenn Ihr Zielcode geöffnet wird, und dann den sleepBefehl 29 Minuten lang verwenden und dann ausführen xdotool key aoder etwas beliebiges ausführen , um den Computer wach zu halten.

Philshem
quelle
2
Für xdo ist es wahrscheinlich besser, einen Schlüssel auszuwählen, der von Natur aus nichts bewirkt. Wenn Sie beispielsweise die Umschalttaste drücken, wird der Bildschirm aktiviert, ohne dass Sie das aktive Fenster eingeben müssen.
Oli
1
Danke. Ich habe in der ursprünglichen Frage absichtlich ein paar Details versteckt. Ich möchte ausdrücklich verhindern, dass mein PC (der Medieninhalte über NFS bereitstellt) angehalten wird, während mein Media Center darauf zugreift. Wenn Sie einen Weg kennen, um dies spezifisch anzugehen, wäre das großartig, andernfalls sehe ich einige Möglichkeiten, die es ermöglichen, dass dies über Koffein funktioniert (z. B. wird das Media Center alle 10 Minuten in meinen PC ssh und ein Shell-Skript ausführen, das schläft für 15 Minuten).
Zorn
1
Ich habe Caffeine ausprobiert und es scheint zu funktionieren, außer dass, sobald das laufende Programm verschwindet, die Caffeine-Ausgabe besagt, dass Suspend nicht mehr gesperrt ist, aber ich habe es für die doppelte Inaktivitätsperiode belassen und obwohl der Bildschirm angehalten hat, hat der PC dies nie getan. Ich werde weiter damit herumspielen, obwohl die xdo-Route wahrscheinlich noch bequemer sein wird, und ich werde das zuerst versuchen. PS Gibt es eine Möglichkeit, eine neue Zeile in einen Kommentar einzufügen?!
Zorn
5

Wenn

  1. Ein Skript in /usr/lib/pm-utils/sleep.d kann überprüfen, ob die Anwendung ausgeführt wird, und 1 zurückgeben, um anzugeben, dass das Anhalten verhindert werden soll.
  2. Das Problem "Das System gibt das automatische Anhalten auf, anstatt es nach weiteren 30 Minuten erneut zu versuchen" wird durch Bewegen der Maus gelöst, die den Timer erneut startet (ich hoffe, ich habe richtig verstanden, was Sie damit meinen).

Warum dann nicht einfach mit dem Mauszeiger wackeln, nachdem die Anwendung beendet wurde?

Zusammenfassen:

  1. Verwenden Sie sleep.d, um zu verhindern, dass das System angehalten wird.
  2. Schreiben Sie ein Skript, das die Maus einmal wackelt.
  3. Rufen Sie 'Long-running-script && mousejiggle' auf.

Dies wird den Bildschirmschoner nicht behindern.

Das einzige Problem ist, dass es 30 Minuten nach Beendigung des Prozesses dauert, wenn das System angehalten wird. Dies ist auch bei Ihrer 'EDIT'-Lösung der Fall.

PS: Ich habe nach einer Lösung für ein ähnliches Problem gesucht, als ich auf dieser Seite von xdotool erfahren habe. So danke. Hoffe das hilft.

S Prasanth
quelle
Genial, danke! Ich werde es dieses Wochenende versuchen.
Zorn
Der Hinweis pm-utilsdazu hat geholfen. Beachten Sie, dass das Paket pm-utilsinstalliert werden muss, damit dies funktioniert. Das Verzeichnis selbst kann auch dann vorhanden sein, wenn das Paket nicht installiert ist.
krlmlr
1

Obwohl EDIT 2 den Bildschirmschoner einschalten lässt und den Autosuspend-Dienst beim Entfernen der Sperrdatei wieder aufnimmt, dauert es 30 Minuten nach dem Entfernen der Datei, bis das System angehalten wird.

Eine mögliche Lösung besteht darin, die integrierte Funktion zum automatischen Bildschirmschoner und zum automatischen Anhalten zu deaktivieren, sie selbst zu implementieren und das Verhalten des Timers nach Bedarf auszuwählen. Der Befehl xprintidle(Möglicherweise müssen Sie dies installieren.) Gibt die Anzahl der Millisekunden aus, für die keine Tastatur- oder Mausaktivität stattgefunden hat. Dies eröffnet mehrere Möglichkeiten. Ich habe den folgenden Inaktivitätsmanager in Python implementiert (kein allzu großer Bash-Scripter). Zu den Funktionen gehören das Festlegen des Befehls, des Timeouts und der Sperrdatei (ich habe sie als Sperre bezeichnet) für Bildschirmschoner und / oder Autosuspend. Darüber hinaus können Sie auswählen, ob der Inaktivitäts-Timer neu gestartet werden soll, wenn die Sperrdatei entfernt wird oder nicht (das Verhalten kann für Suspend und Bildschirmschoner unterschiedlich sein). Ich habe versucht, die Verwendung in den Notizen klar zu machen, aber wenn etwas unklar ist, fragen Sie.

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

Verwendungszweck:

  1. inactivitymanager &Fügen Sie einfach zu .profile oder .xsessionrc im Home-Verzeichnis hinzu (sehen Sie, welches für Sie funktioniert. Fügen Sie nicht beide hinzu, da sonst zwei Instanzen dieses Skripts gleichzeitig ausgeführt werden, was ich nicht behandelt habe. Ich denke, es liegt in diesen Details dass die Mainstream-Implementierungen die benutzerdefinierten übertreffen).
  2. Möglicherweise müssen Sie xprintidle installieren.

Wie die Sperrdatei dorthin gelangt, bleibt vorerst der Vorstellungskraft des Benutzers überlassen (wenn ich mich dazu bringe, einen Daemon dafür zu implementieren, werde ich dies in eine EDIT auf diese Antwort einfügen). Sie (OP) haben es natürlich für Ihren Fall gelöst. Eine Gefahr, die Sie vermeiden sollten, wenn Sie versuchen, das Anhalten für mehr als einen Prozess zu verhindern, ist das Löschen der Sperrdatei, wenn ein Prozess beendet wird, während ein anderer noch ausgeführt wird. Alternativ kann das Skript leicht bearbeitet werden, um das Anhalten zu verhindern, wenn eine Datei in einem bestimmten Verzeichnis (einem Sperrverzeichnis) vorhanden ist. Auf diese Weise kann jeder Prozess eine eigene Sperrdatei haben.

Anmerkungen:

  1. Dieses Skript schont den Prozessor und den Speicher. Das Entfernen der time.sleep (1) s im Code kann jedoch zu Problemen führen - wurde jedoch nicht überprüft.
  2. Für pm-suspend sind Sudo-Berechtigungen erforderlich. Um eine PM-Suspendierung ohne Kennwortprüfung durchzuführen Wie führe ich bestimmte Sudo-Befehle ohne Kennwort aus? . Alternativ können Sie dieses Skript im Sudo-Modus ausführen und dieses Skript ohne Kennwort sudofähig machen (kein Problem, wenn Sie das Skript als Root ausführen).
  3. Das Skript kann Probleme bekommen, wenn die Zeitüberschreitung auf weniger als ~ 10 Sekunden eingestellt ist (ich glaube, ich muss nicht überprüfen, wo genau der Fehler beginnt, muss weniger als 5 betragen). Dies kann durch Entfernen einiger time.sleep (1) s auf Kosten der Systemressourcen behoben werden. Glaube aber nicht, dass irgendjemand das brauchen wird.
  4. Da wir die Timer im Griff haben, sind keine Mausbewegungen erforderlich!
S Prasanth
quelle