Как временно приостановить приостановку?

10

Я немного обыскал это и не могу найти ничего полезного.

Мой компьютер работает под управлением Ubuntu 12.10 и настроен на приостановку после 30 минут бездействия. Я не хочу это менять, большую часть времени это прекрасно работает.

Что я хочу сделать, так это отключить автоматическую приостановку, если работает конкретное приложение. Как я могу это сделать?

Самое близкое, что я нашел на данный момент, - это добавить сценарий оболочки, в /usr/lib/pm-utils/sleep.dкотором проверяется, запущено ли приложение, и возвращает 1, чтобы указать, что приостановка должна быть предотвращена. Но похоже, что система перестает автоматически приостанавливаться, вместо повторных попыток через 30 минут. (Насколько я могу судить, если я переместлю мышь, это снова перезапустит таймер.) Вполне вероятно, что приложение завершит работу через пару часов, и я бы предпочел, чтобы мой компьютер автоматически приостанавливался, если я не использую это в тот момент . (Поэтому я не хочу добавлять вызов pm-suspend после завершения приложения.)

Это возможно?

РЕДАКТИРОВАТЬ: Как я отметил в одном из комментариев ниже, что я действительно хотел, чтобы запретить приостановку, когда мой компьютер обслуживал файлы через NFS; Я просто хотел сосредоточиться на «приостановить» часть вопроса, потому что у меня уже была идея, как решить часть NFS. Используя идею «xdotool», приведенную в одном из ответов, я придумал следующий скрипт, который запускаю из cron каждые несколько минут. Это не идеально, потому что он останавливает заставку, но она работает. Мне нужно взглянуть на то, почему «кофеин» не корректно повторно включает приостановку позже, тогда я мог бы, вероятно, добиться большего успеха. В любом случае, похоже, это работает, поэтому я включу его сюда на случай, если кому-то еще будет интересно.

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

РЕДАКТИРОВАТЬ 2: Сценарий выше работает, но благодаря другому комментарию ниже, я теперь использую эту пару сценариев, которые имеют преимущество, позволяющее заставке включаться, пока я запрещаю приостановку. Первым является /usr/lib/pm-utils/sleep.d/000nfs-inhibit, который предотвратит попытку приостановки, если существует файл запрета:

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

Второй - модифицированная версия предыдущего скрипта nfs-suspend-blocker, и он все равно должен запускаться из cron. Теперь он следует стратегии, изложенной в комментарии ниже:

#!/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
Зорн
источник
Вместо того, чтобы загромождать вопрос, вы должны поставить свои два решения этой проблемы в качестве ответа ниже.
Cas

Ответы:

8

Программа для бодрствования вашего компьютера - это кофеин . Я хотел бы создать файл .bash_aliases, чтобы он также вызывал кофеин при вызове вашего исходного кода.

alias newname="origcode && caffeine"

В зависимости от того, какой код вы пытаетесь держать на своем компьютере, вам придется создать собственный сценарий, который включает в себя уничтожение кофеина, когда другой код остановлен. Некоторые подробности о конкретном коде помогут.

Обновление: более простой способ - запустить xdotool , который можно установить с помощью sudo apt-get install xdotool. Вы можете написать сценарий, который вызывается при открытии целевого кода, а затем использовать sleepкоманду в течение 29 минут, а затем выполнить xdotool key aили что-то произвольное, чтобы не дать компьютеру проснуться.

philshem
источник
2
Для xdo, вероятно, лучше выбрать ключ, который по своей сути ничего не делает. Например, нажатие клавиши shift приведет к пробуждению экрана без ввода текста в активном окне.
Оли
1
Спасибо. Я намеренно скрывал немного деталей в исходном вопросе - я явно хочу сделать так, чтобы мой компьютер (который обслуживает мультимедийный контент через NFS) приостанавливался, пока мой медиацентр обращается к нему. Если вы знаете способ конкретно решить эту проблему, это было бы замечательно, в противном случае я могу увидеть пару путей, которые позволят этому работать через кофеин (например, медиацентр будет подключаться к моему ПК каждые 10 минут и запускать сценарий оболочки, который спит на 15 минут).
Цорн
1
Я попробовал кофеин, и он, кажется, работает, за исключением того, что после того, как запущенная программа исчезает, вывод кофеина говорит, что приостановка больше не блокируется, но я оставлял ее в течение периода бездействия в два раза, и хотя экран приостанавливал работу ПК, этого не происходило. Я поиграю с этим дальше, хотя маршрут xdo, вероятно, будет еще более удобным, и я попробую сначала. PS Есть ли способ вставить новую строку в комментарий ?!
Цорн
5

Если

  1. Сценарий в /usr/lib/pm-utils/sleep.d может проверить, запущено ли приложение, и вернуть 1, чтобы указать, что приостановка должна быть предотвращена.
  2. Проблема «система перестает автоматически приостанавливаться, вместо повторных попыток через 30 минут» решается перемещением мыши, которая снова запускает таймер (надеюсь, я правильно понял, что вы имеете в виду под этим)

тогда почему бы просто не трясти указателем мыши после завершения работы приложения.

Чтобы обобщить:

  1. Используйте sleep.d, чтобы система не зависала.
  2. Напишите скрипт, который покачивает мышь один раз.
  3. Вызовите «Long-running-script && mousejiggle»

Это не помешает заставке.

Единственная проблема заключается в том, что пройдет 30 минут после завершения процесса, когда система приостановит работу. Это относится и к вашему решению «РЕДАКТИРОВАТЬ».

PS: я искал решение подобной проблемы, когда узнал о xdotool на этой странице. Тогда спасибо. Надеюсь это поможет.

S Prasanth
источник
Гениально, спасибо! Я попробую в эти выходные.
Цорн
pm-utilsПомог намек по поводу . Обратите внимание, что пакет pm-utilsдолжен быть установлен, чтобы это работало - сам каталог может существовать, даже если пакет не установлен.
krlmlr
1

Хотя EDIT 2 позволяет активировать заставку и возобновляет службу автоматического приостановления при удалении файла блокировки, как было отмечено выше, через 30 минут после удаления файла система будет приостановлена.

Одним из возможных решений является отключение встроенных функций автоэкранной заставки и автоматического приостановления и их реализация самостоятельно, а также выбор поведения таймера по мере необходимости. Команда xprintidle(возможно, вам придется установить это) печатает количество миллисекунд, в течение которых не было никаких действий клавиатуры или мыши. Это открывает несколько возможностей. Я реализовал следующий менеджер неактивности в python (не слишком много скриптов bash). Возможности включают в себя настройку команды, тайм-аут и запретить файл (я назвал это блокировкой) для заставки и / или автоподключения. Кроме того, есть возможность выбрать, должен ли таймер неактивности перезапускаться при удалении запрещающего файла или нет (поведение может быть различным для приостановки и хранителя экрана). Я пытался объяснить использование в примечаниях, но если что-то неясно, спросите.

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

Применение:

  1. Просто добавьте inactivitymanager &в .profile или .xsessionrc в домашнем каталоге (посмотрите, какой из них работает для вас. Не добавляйте в обоих, иначе два экземпляра этого скрипта будут работать одновременно, что я не обработал. Я думаю, что это в этих деталях что основные реализации превзойдут пользовательские).
  2. Возможно, вам придется установить xprintidle.

Как файл запрета попадает туда, пока остается на усмотрение пользователя (если я заставлю себя реализовать демон для этого, я добавлю это в РЕДАКТИРОВАТЬ к этому ответу). Вы (OP), конечно, решили это для своего случая. Одна из ловушек, которую следует избегать при попытке запретить приостановку для более чем одного процесса, - это удаление файла блокировки, когда один процесс завершается, а другой еще работает. Кроме того, сценарий может быть немного отредактирован, чтобы запретить приостановку, если какой-либо файл существует в определенном каталоге (каталог блокировки). Таким образом, каждый процесс может иметь свой собственный файл блокировки.

Ноты:

  1. Этот скрипт довольно легкий на процессоре и памяти. Но удаление time.sleep (1) в коде может вызвать проблемы - пока не проверено.
  2. pm-suspend требует разрешения sudo. Чтобы pm-suspend без предоставления пароля извлечения Как я могу запустить определенные команды sudo без пароля? , В качестве альтернативы вы можете запустить этот скрипт в режиме sudo и сделать этот скрипт пригодным для использования без пароля (не проблема, если вы запускаете скрипт как root)
  3. Сценарий может столкнуться с проблемами, если время ожидания не превышает ~ 10 секунд (я думаю, я не проверял, где именно начинается проблема, должно быть меньше 5). Это можно сделать, удалив некоторые time.sleep (1) за счет системных ресурсов. Не думайте, что кому-то это понадобится.
  4. Поскольку у нас есть ручка для таймеров, никаких манипуляций с мышью не требуется!
S Prasanth
источник