Jak tymczasowo wstrzymać zawieszenie?

10

Szukałem tego trochę i nie mogę znaleźć nic pomocnego.

Mam komputer z systemem Ubuntu 12.10 skonfigurowany do zawieszenia po 30 minutach bezczynności. Nie chcę tego zmieniać, przez większość czasu działa świetnie.

Chcę tylko wyłączyć automatyczne zawieszanie, jeśli dana aplikacja jest uruchomiona. W jaki sposób mogę to zrobić?

Najbliższą rzeczą, jaką do tej pory znalazłem, jest dodanie skryptu powłoki, w /usr/lib/pm-utils/sleep.dktórym sprawdza, czy aplikacja działa, i zwraca 1, aby wskazać, że należy zapobiec zawieszeniu. Wygląda jednak na to, że system zrezygnuje z automatycznego zawieszania, zamiast próbować ponownie po kolejnych 30 minutach. (O ile mogę stwierdzić, jeśli poruszę myszą, to ponownie uruchomi stoper ponownie.) Jest całkiem prawdopodobne, że aplikacja zakończy się po kilku godzinach, a wolałbym, żeby mój komputer zawiesił się automatycznie, jeśli nie używam w tym momencie . (Więc nie chcę dodawać połączenia do PM-Suspend po zakończeniu aplikacji).

czy to możliwe?

EDYCJA: Jak zauważyłem w jednym z poniższych komentarzy, tak naprawdę chciałem powstrzymać zawieszanie, gdy mój komputer wyświetlał pliki przez NFS; Chciałem tylko skupić się na części „zawieszenia” pytania, ponieważ już miałem pomysł, jak rozwiązać część NFS. Korzystając z pomysłu „xdotool” podanego w jednej z odpowiedzi, wymyśliłem następujący skrypt, który uruchamiam z crona co kilka minut. Nie jest to idealne rozwiązanie, ponieważ zatrzymuje również włączanie się wygaszacza ekranu, ale działa. Muszę rzucić okiem na to, dlaczego „kofeina” nie włącza poprawnie później zawieszenia, to prawdopodobnie mogłabym to zrobić lepiej. W każdym razie wydaje się, że to działa, więc włączam to tutaj na wypadek, gdyby ktoś był zainteresowany.

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

EDYCJA 2: Powyższy skrypt działa, ale dzięki kolejnemu komentarzowi poniżej korzystam teraz z tej pary skryptów, które mają tę zaletę, że pozwalają na uruchomienie wygaszacza ekranu podczas wstrzymywania zawieszenia. Pierwszy to /usr/lib/pm-utils/sleep.d/000nfs-inhibit, który zapobiegnie próbie zawieszenia, jeśli istnieje plik wstrzymania:

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

Druga to zmodyfikowana wersja poprzedniego skryptu nfs-suspend-blocker i nadal powinna być uruchamiana z crona. Teraz jest zgodny ze strategią opisaną w komentarzu poniżej:

#!/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
źródło
Zamiast zaśmiecać pytanie, powinieneś postawić swoje dwa rozwiązania problemu jako odpowiedź poniżej.
Cas

Odpowiedzi:

8

Programem do czuwania komputera jest kofeina . Zrobiłbym plik .bash_aliases, aby wywoływał również kofeinę, gdy wywoływany jest twój oryginalny kod.

alias newname="origcode && caffeine"

W zależności od kodu, dla którego próbujesz utrzymać komputer w stanie czuwania, będziesz musiał stworzyć niestandardowy skrypt, który obejmuje zabijanie kofeiny po zatrzymaniu drugiego kodu. Przydałoby się więcej szczegółów na temat konkretnego kodu.

Aktualizacja: Prostszym sposobem byłoby uruchomienie xdotool , który można zainstalować za pomocą sudo apt-get install xdotool. Możesz napisać skrypt, który jest wywoływany po otwarciu kodu docelowego, a następnie użyj sleeppolecenia przez 29 minut, a następnie uruchom xdotool key alub coś innego, aby utrzymać komputer w stanie czuwania.

philshem
źródło
2
W przypadku xdo prawdopodobnie lepiej jest wybrać klucz, który z natury nic nie robi. Na przykład naciśnięcie klawisza Shift obudzi ekran bez pisania w aktywnym oknie.
Oli
1
Dziękuję Ci. Celowo ukrywałem trochę szczegółów w pierwotnym pytaniu - to, co wyraźnie chcę zrobić, to zatrzymać zawieszanie się mojego komputera (który obsługuje treści multimedialne przez NFS), gdy moje centrum multimedialne ma do niego dostęp. Jeśli znasz sposób na rozwiązanie tego problemu, byłoby świetnie, w przeciwnym razie widzę kilka sposobów, które pozwolą na to za pośrednictwem Caffeine (np. Centrum multimedialne będzie ssh na moim komputerze co 10 minut i uruchomi skrypt powłoki, który śpi przez 15 minut).
Zorn
1
Wypróbowałem kofeinę i wydaje się, że działa, ale po zniknięciu uruchomionego programu kofeina mówi, że zawieszenie nie jest już wstrzymywane, ale zostawiłem go na okres bezczynności i chociaż ekran zawieszony komputer nigdy tego nie zrobił. Będę się tym zajmować dalej, chociaż prawdopodobnie droga xdo będzie jeszcze wygodniejsza i spróbuję tego w pierwszej kolejności. PS Czy jest jakiś sposób na wstawienie nowego wiersza w komentarzu ?!
Zorn
5

Gdyby

  1. Skrypt w /usr/lib/pm-utils/sleep.d może sprawdzić, czy aplikacja jest uruchomiona i zwrócić 1, aby wskazać, że należy zapobiec zawieszeniu.
  2. Problem „system następnie rezygnuje z automatycznego zawieszania, zamiast ponawiać próbę po kolejnych 30 minutach”, został rozwiązany przez przesunięcie myszy, która ponownie uruchamia stoper (mam nadzieję, że dobrze zrozumiałem, co masz na myśli)

to dlaczego po prostu nie poruszać wskaźnikiem myszy po zakończeniu aplikacji.

Podsumować:

  1. Użyj sleep.d, aby zatrzymać zawieszanie systemu.
  2. Napisz skrypt, który raz poruszy myszką.
  3. Nazwij „Long-running-script && mousejiggle”

Nie utrudni to wygaszacza ekranu.

Jedynym problemem jest to, że minie 30 minut od zakończenia procesu, gdy system zawiesi się. Tak jest również w przypadku rozwiązania „EDIT”.

PS: Szukałem rozwiązania podobnego problemu, kiedy dowiedziałem się o xdotool z tej strony. Więc dziękuję. Mam nadzieję że to pomoże.

S Prasanth
źródło
Pomysłowy, dziękuję! Spróbuję w ten weekend.
Zorn
Wskazówka dotycząca pm-utilspomogła. Zauważ, że pakiet pm-utilsmusi zostać zainstalowany, aby to działało - sam katalog może istnieć, nawet jeśli pakiet nie jest zainstalowany.
krlmlr
1

Chociaż EDIT 2 pozwala na uruchomienie wygaszacza ekranu i wznawia usługę automatycznego zawieszania po usunięciu pliku wstrzymania, jak wspomniano powyżej, upłynie 30 minut po usunięciu pliku, gdy system zawiesi się.

Jednym z możliwych rozwiązań jest wyłączenie wbudowanej funkcji automatycznego wygaszacza ekranu i automatycznego zawieszania oraz samodzielne wdrożenie ich i wybranie zachowania timera zgodnie z wymaganiami. Polecenie xprintidle(być może trzeba to zainstalować) drukuje liczbę milisekund, dla których nie było żadnej aktywności klawiatury lub myszy. Otwiera to kilka możliwości. Zaimplementowałem następujący menedżer nieaktywności w Pythonie (niezbyt dużo skryptu bash). Funkcje obejmują ustawienie polecenia, limit czasu i blokowanie pliku (nazwałem to blokada) dla wygaszacza ekranu i / lub automatycznego zawieszania. Ponadto istnieje możliwość wyboru, czy licznik czasu braku aktywności ma się restartować po usunięciu pliku wstrzymania, czy nie (zachowanie może być inne dla zawieszenia i wygaszacza ekranu). Próbowałem wyjaśnić użycie w notatkach, ale jeśli coś jest niejasne, zapytaj.

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

Stosowanie:

  1. Po prostu dodaj inactivitymanager &do .profile lub .xsessionrc w katalogu domowym (zobacz, który z nich działa dla ciebie. Nie dodawaj obu, w przeciwnym razie uruchomią się jednocześnie dwa wystąpienia tego skryptu, coś, czego nie obsłużyłem. Myślę, że jest to w tych szczegółach implementacje głównego nurtu atutują niestandardowe).
  2. Być może będziesz musiał zainstalować xprintidle.

Sposób, w jaki dostaje się tam plik wstrzymania, pozostaje teraz w wyobraźni użytkownika (jeśli zmusię się do zaimplementowania w tym celu demona, wstawię to do EDYCJI tej odpowiedzi). Ty (OP) oczywiście rozwiązałeś to dla swojej sprawy. Jedną pułapką, której należy unikać przy próbie zahamowania zawieszenia dla więcej niż jednego procesu, jest usunięcie pliku blokady, gdy jeden proces kończy się, gdy inny jest nadal uruchomiony. Alternatywnie skrypt można nieznacznie edytować, aby zatrzymać zawieszanie, jeśli jakiś plik istnieje w określonym katalogu (katalogu blokady). W ten sposób każdy proces może mieć własny plik blokady.

Uwagi:

  1. Ten skrypt jest dość lekki dla procesora i pamięci. Ale usunięcie time.sleep (1) s w kodzie może powodować problemy - chociaż nie sprawdziłem.
  2. pm-suspend wymaga uprawnień sudo. Aby PM-zawiesić bez podawania hasła Jak uruchomić określone polecenia sudo bez hasła? . Alternatywnie możesz uruchomić ten skrypt w trybie sudo i ustawić ten skrypt jako sudoable bez hasła (nie ma problemu, jeśli skrypt jest uruchamiany jako root)
  3. Skrypt może mieć problemy, jeśli limity czasu są ustawione na mniej niż ~ 10 sekund (chyba nie sprawdzam, gdzie dokładnie zaczyna się problem, chyba mniej niż 5). Można to rozwiązać, usuwając niektóre time.sleep (1) kosztem zasobów systemowych. Nie sądzę jednak, że ktoś będzie tego potrzebował.
  4. Ponieważ mamy kontrolę nad zegarami, nie potrzeba żadnych ruchów myszy!
S Prasanth
źródło