Como inibir suspender temporariamente?

9

Eu pesquisei um pouco sobre isso e não consigo encontrar nada de útil.

Eu tenho meu PC rodando Ubuntu 12.10 configurado para suspender após 30 minutos de inatividade. Eu não quero mudar isso, funciona muito bem na maior parte do tempo.

O que eu quero fazer é desativar a suspensão automática se um aplicativo específico estiver em execução. Como posso fazer isso?

A coisa mais próxima que encontrei até agora é adicionar um script de shell em /usr/lib/pm-utils/sleep.d , que verifica se o aplicativo está em execução e retorna 1 para indicar que a suspensão deve ser evitada. Mas parece que o sistema desiste de suspender automaticamente, em vez de tentar novamente depois de mais 30 minutos. (Tanto quanto eu posso dizer, se eu mover o mouse, isso reinicia o cronômetro novamente.) É bem provável que o aplicativo seja concluído depois de algumas horas, e prefiro que meu PC seja suspenso automaticamente se eu ' não estou usando nesse ponto . (Então eu não quero adicionar uma chamada para pm-suspender quando o aplicativo terminar.)

Isso é possível?

EDIT: Como eu observei em um dos comentários abaixo, o que eu realmente queria era inibir a suspensão quando meu PC estava servindo arquivos através do NFS; Eu só queria focar na parte "suspender" da questão porque eu já tinha uma idéia de como resolver a parte NFS. Usando a idéia 'xdotool' dada em uma das respostas, eu criei o seguinte script que eu executo do cron a cada poucos minutos. Não é o ideal porque também pára o protetor de tela, mas funciona. Eu preciso dar uma olhada no porquê a 'cafeína' não reabilitar corretamente a suspensão mais tarde, então eu provavelmente poderia fazer melhor. De qualquer forma, isso parece funcionar, então estou incluindo aqui, caso alguém esteja interessado.

#!/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: O script acima funciona, mas graças a outro comentário abaixo, estou usando agora este par de scripts, que tem a vantagem de permitir que o protetor de tela entre em ação enquanto eu estou inibindo a suspensão. A primeira é /usr/lib/pm-utils/sleep.d/000nfs-inhibit, que impedirá uma tentativa de suspensão se existir um arquivo de inibição:

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

O segundo é uma versão modificada do script anterior nfs-suspend-blocker e ainda deve ser executado a partir do cron. Agora segue a estratégia descrita no comentário abaixo:

#!/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
    
por Zorn 26.11.2012 / 22:31

3 respostas

7

Um programa para manter seu computador acordado é Cafeína . Eu faria um arquivo .bash_aliases para também chamar cafeína quando seu código original for chamado.

alias newname="origcode && caffeine"

Dependendo do código para o qual você está tentando manter seu computador ativo, você precisará criar um script personalizado que inclua a morte de cafeína quando o outro código for interrompido. Mais alguns detalhes sobre o código em particular ajudariam.

Atualização: Uma maneira mais simples seria executar xdotool , que pode ser instalado com sudo apt-get install xdotool . Você pode escrever um script que é chamado quando seu código de destino é aberto e, em seguida, usar o comando sleep por 29 minutos e, em seguida, executar xdotool key a ou algo arbitrário para manter o computador ativo.

    
por philshem 26.11.2012 / 22:39
5

Se

  1. Um script em /usr/lib/pm-utils/sleep.d pode verificar se o aplicativo está em execução e retornar 1 para indicar que a suspensão deve ser evitada.
  2. O problema de "o sistema então desiste de suspender automaticamente, em vez de tentar novamente após 30 minutos" é resolvido movendo o mouse que reinicia o cronômetro novamente (espero ter entendido corretamente o que você quer dizer com isso)

por que não apenas agitar o ponteiro do mouse após o término do aplicativo.

Para resumir:

  1. Use sleep.d para impedir que o sistema seja suspenso.
  2. Escreva um script que agite o mouse uma vez.
  3. Chamar "script de longa duração & & mousejiggle '

Isso não atrapalha o protetor de tela.

O único problema é que serão 30 minutos após o processo terminar quando o sistema for suspenso. Este é o caso da sua solução 'EDIT' também.

PS: Eu estava procurando uma solução para um problema similar quando soube do xdotool desta página. Então obrigado. Espero que isso ajude.

    
por S Prasanth 30.11.2012 / 12:51
1

Embora o EDIT 2 permita que o protetor de tela inicie e reinicie o serviço de suspensão automática na remoção do arquivo de inibição, como observado acima, serão 30 minutos após o arquivo ser removido quando o sistema for suspenso.

Uma solução possível é desabilitar a funcionalidade de autocromoção de tela e suspensão automática embutida e implementá-la por nossa conta e escolher o comportamento do cronômetro conforme necessário. O comando xprintidle (talvez você tenha que instalar isso) imprime o número de milissegundos para os quais não houve atividade de teclado ou mouse. Isso abre várias possibilidades. Eu implementei o seguinte gerenciador de inatividade em python (não muito de um script bash). Os recursos incluem a configuração do comando, o tempo limite e o arquivo de inibição (chamado bloqueio) para proteção de tela e / ou suspensão automática. Além disso, existe a opção de escolher se o temporizador de inatividade deve reiniciar quando o arquivo de inibição é removido ou não (o comportamento pode ser diferente para a suspensão e o protetor de tela). Eu tentei deixar claro o uso nas notas, mas se algo não estiver claro, pergunte.

#!/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://sobrelinux.info/questions/25/how-do-i-run-specific-sudo-commands-without-a-password"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. Basta adicionar inactivitymanager & a .profile ou .xsessionrc no diretório inicial (veja qual deles funciona para você. Não inclua ambos, senão duas instâncias desse script serão executadas simultaneamente, algo que eu não manipulei. acho que é nesses detalhes que as implementações tradicionais superam as personalizadas).
  2. Você pode ter que instalar o xprintidle.

Como o arquivo de inibição chega lá é deixado para a imaginação do usuário por enquanto (se eu me forçar a implementar um daemon para isso, colocarei isso em um EDIT nesta resposta). Você (OP), é claro, resolveu o problema para o seu caso. Uma armadilha a ser evitada ao tentar inibir a suspensão em mais de um processo é excluir o arquivo de bloqueio quando um processo termina enquanto outro ainda está em execução. Como alternativa, o script pode ser modificado para inibir a suspensão se algum arquivo existir em um diretório específico (um diretório de bloqueio). Dessa forma, cada processo pode ter seu próprio arquivo de bloqueio.

Notas:

  1. Este script é bastante leve no processador e na memória. Mas remover o time.sleep (1) s no código pode causar problemas - ainda não foi verificado.
  2. pm-suspend requer permissões sudo. Para pm-suspender sem dar checkout de senha Como eu executo comandos sudo específicos sem uma senha? . Alternativamente, você pode executar este script no modo sudo, e fazer este script sudoable sem senha (Não é um problema se você está executando o script como root)
  3. O script pode ter problemas se os tempos limite estiverem definidos para menos de ~ 10 segundos (não sei onde exatamente o problema começa deve ser menor que 5, eu acho). Isso pode ser resolvido removendo algum time.sleep (1) s às custas dos recursos do sistema. Não pense que alguém precisará disso.
  4. Porque nós temos um controle sobre os timers, nenhum mousejiggles é necessário!
por S Prasanth 02.12.2012 / 12:15