Execute um comando quando o sistema estiver inativo e quando estiver ativo novamente

15

Quero executar um comando quando o usuário ficar inativo (o sistema está ocioso). Por exemplo:

echo "You started to be inactive."

Além disso, quando o usuário se torna ativo novamente (o sistema não está mais ocioso):

echo "You started to be active, again."

Eu preciso de um script de shell que faça isso. Isso é possível sem um temporizador / intervalo? Talvez alguns eventos do sistema?

Ionică Bizău
fonte
2
Você pode entrar em detalhes um pouco mais profundos sobre o que realmente deseja alcançar?
Nils
3
Como você mede a ociosidade? Um usuário está assistindo a um filme ocioso (porque ele não está interagindo com o computador)? Um usuário que está conectado remotamente está ativo?
Gilles 'SO- stop be evil'
Pelo que sei, o sistema tem esse conceito embutido: ocioso , ativo etc. Está certo?
Jonic Biz
@ IonicăBizău: Na verdade não. Inativo no contexto do sistema significaria apenas que todos os processos estão inativos , ou seja, "esperando por algo". Embora isso possa acontecer com bastante frequência em um sistema moderno e até seja o caso na maioria das vezes, ele não permanece assim enquanto houver sempre algo a ser feito e se estiver atualizando o relógio. A ociosidade , especialmente no contexto da sua pergunta, é mais uma função do usuário do que do sistema e até do que geralmente está vinculada a uma sessão específica.
Adaephon
@Adaephon Ok. No meu conceito, um sistema fica ocioso quando o usuário não realiza nenhuma ação (movimento do mouse, clique, tecla pressionada) no computador por x minutos. O sistema se torna ativo quando o usuário executa a primeira ação: clica em um botão do mouse, move-o, pressiona uma tecla e assim por diante. É possível detectar esses estados ativos inativos * / * usando um script de shell?
Jonic Biz

Respostas:

17

Esse tópico nos fóruns do ArchLinux contém um pequeno programa C que consulta o xscreensaver para obter informações sobre quanto tempo o usuário está ocioso, e isso parece bem próximo dos seus requisitos:

#include <X11/extensions/scrnsaver.h>
#include <stdio.h>

int main(void) {
    Display *dpy = XOpenDisplay(NULL);

    if (!dpy) {
        return(1);
    }

    XScreenSaverInfo *info = XScreenSaverAllocInfo();
    XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info);
    printf("%u\n", info->idle);

      return(0);
}

Salve isso getIdle.ce compile com

gcc -o getIdle getIdle.c -lXss -lX11

para obter um arquivo executável getIdle. Este programa imprime o "tempo ocioso" (o usuário não se move / clica com o mouse, não usa o teclado) em milissegundos, portanto, um script bash que se baseia nele pode ter a seguinte aparência:

#!/bin/bash

idle=false
idleAfter=3000     # consider idle after 3000 ms

while true; do
  idleTimeMillis=$(./getIdle)
  echo $idleTimeMillis  # just for debug purposes.
  if [[ $idle = false && $idleTimeMillis -gt $idleAfter ]] ; then
    echo "start idle"   # or whatever command(s) you want to run...
    idle=true
  fi

  if [[ $idle = true && $idleTimeMillis -lt $idleAfter ]] ; then
    echo "end idle"     # same here.
    idle=false
  fi
  sleep 1      # polling interval

done

Isso ainda precisa de pesquisas regulares, mas faz tudo o que você precisa ...

Jaspe
fonte
Funciona como deveria! +1
Ionică Bizău
Você vale mais pontos!
Ionică Bizău
2
Você pode economizar a compilar seu próprio programa e apenas usá-lo xprintidle, que está disponível na maioria das distribuições e faz exatamente a mesma coisa.
Motim
3

O TMOUT no bash encerrará uma sessão interativa após o número de segundos definido. Você pode usar esse mecanismo.

Você pode capturar o logout configurando uma armadilha de acordo (não testei isso) ou usando os scripts bash-logout (~ / .bash_logout).

Aqui está uma boa resposta do superusuário nessa direção.

Nils
fonte
Isso não aborda como o usuário executaria um comando, em vez de efetuar logout, após $TMOUTsegundos.
chepner
Você pode adicionar mais informações à sua resposta? Ainda não está claro para mim ... #
23314
@chepner Adicionei mais alguns detalhes à minha resposta.
Nils
De qualquer forma, isso simplesmente desconecta o usuário após o tempo terminar. Acho que não há como interromper o logout, seja de uma EXITarmadilha ou de .bash_logout.
chepner
3

Isso não é exatamente o que você solicitou, mas sempre existe o batchcomando-(geralmente uma chamada especial do atcomando atd-e usando o -daemon).

batchpermite que você solicite a execução de um comando quando a média de carga cair abaixo de um determinado limite (geralmente 1,5, mas isso pode ser definido ao iniciar atd). Com atisso, também é possível contratar um emprego de tal maneira que, em vez de ser executado em um determinado momento; o trabalho acaba de ser entregue batchnaquele momento e é executado pela primeira vez quando a média de carga cai (por exemplo, é executada assim que a média de carga cai para menos de 1,5 em algum momento após as 02:00).

Infelizmente, um trabalho em lotes será executado até o fim; não será interrompido se o computador não estiver mais ocioso.

+++

Se você tem que ir a programação de rota (que parece que a partir de outras respostas), eu acho que eu iria tentar fazer algo semelhante ao atdou cronddaemons, que monitorava os usuários conectados e / ou média-carga. Este daemon pode então executar scripts / programas a partir de um determinado diretório e iniciar / continuar ou pará-los (com sinais), conforme necessário.

Baard Kopperud
fonte
Se você fizer isso e usar .lockarquivos, poderá lidar facilmente com problemas de tempo.
mikeserv
2

Esse encadeamento possui algumas soluções baseadas na detecção de atividade do teclado e do mouse. Eu corro xprintidlede um trabalho cron que começa a cada poucos minutos. Mas, como eles apontam xprintidle, não é mantida, convém instalar o módulo Perl e usá-lo:

$ cpanm X11::IdleTime
...
$ sleep 10; perl -MX11::IdleTime -le 'print GetIdleTime()'
9

Eu usaria qualquer solução pesquisando a partir do cron, em um script que sai na parte superior se a interface do usuário não estiver suficientemente inativa. Claro que o script precisaria de um export DISPLAY=:0.0para conversar com o X11.

Lembre-se de que o teclado e o mouse podem ficar inativos ao assistir a um filme ou ao executar uma tarefa com muita CPU.

Metamórfico
fonte
1

Não conheço uma maneira de fazer isso sem pesquisar algum tipo de estatística do sistema, como as outras respostas que usam um protetor de tela ou um cronômetro inativo, ou executando a partir de .bash_logout, mas aqui está uma idéia para verificar o uso da CPU.

Isso ainda envolveria sondagens a cada n segundos, e se o uso da CPU estiver abaixo da quantidade que você escolher, poderá criar o script do que deseja executar. No entanto, o que quer que você execute pode aumentar o uso da CPU, mas você pode usar bem suas "coisas" para não contar.

Aqui está um script de teste usando top, mas você pode usar o mpstat ou verificar as médias de carga?

while true
do
idle=$(top -bn2 | grep "Cpu(s)"|tail -n 1|sed "s/.*, *\([0-9.]*\)%* id.*/\1/")
echo "idle is $idle"
if [[ $idle > 90 ]]
then
    echo "idle above 90%"
    echo "Do stuff now"
else
    echo "idle below 90%"
    echo "Stop doing stuff now"
fi
sleep 1
done

Esse é apenas um script que eu montei para testar a leitura da ociosidade de cima. Você pode analisar, /proc/statmas acho que mostra apenas o tempo total e é necessário comparar os resultados ao longo de um intervalo. O Top tem seu próprio problema para mim (linux mint 16); na primeira execução, ele parece nunca mudar o cpustats, como se tivesse que esperar para analisar / proc / stat em si, portanto, top -bn2mas na teoria top -bn1deveria funcionar.

Xen2050
fonte
Ugh ... sério? Sondando as estatísticas da CPU?
Rolf
A propósito, você também pode pesquisar o wcomando que mostra o tempo ocioso do usuário. - Pelo jeito que não estou julgando, é só isso para mim, quero detectar inatividade para colocar a máquina em repouso, para poupar energia, e as pesquisas vão contra isso.
Rolf
@Rolf Parece bastante a julgar ... já que esse comentário realmente não adiciona muito, provavelmente deve ser removido, sim? De qualquer forma, as outras respostas usam o tempo ocioso de algumas maneiras diferentes, mas como você pode detectar o tempo ocioso sem olhar / perguntar ao sistema?
Xen2050