Запустите команду, когда система простаивает и когда снова активна

15

Я хочу выполнить команду, когда пользователь становится неактивным (система бездействует). Например:

echo "You started to be inactive."

Кроме того, когда пользователь снова становится активным (система больше не находится в режиме ожидания):

echo "You started to be active, again."

Мне нужен сценарий оболочки, который сделает это. Это возможно без таймера / интервала? Может быть, какие-то системные события?

Ионика Бизэу
источник
2
Можете ли вы рассказать немного подробнее о том, чего вы на самом деле хотите достичь?
Нильс
3
Как вы измеряете праздность? Пользователь смотрит фильм без дела (потому что он не взаимодействует с компьютером)? Является ли пользователь, вошедший в систему, удаленно активным?
Жиль "ТАК ... перестать быть злым"
Из того, что я знаю, система имеет такую ​​встроенную концепцию: холостой , активный и т. Д. Это правильно?
Ионика Бизэу
@ IonicăBizau: Не совсем. Неактивный в контексте системы будет означать только то, что все процессы спят, то есть «чего-то ждут». Хотя это может происходить довольно часто в современной системе и даже может иметь место в большинстве случаев, это не происходит так долго, поскольку всегда есть что-то, что нужно сделать, и если оно обновляет часы. Праздность , особенно в контексте вашего вопроса, больше зависит от пользователя, чем от системы и даже от того, что обычно связана с конкретным сеансом.
Adaephon
@Adaephon Хорошо. В моей концепции система бездействует, когда пользователь не выполняет никаких действий (перемещение мыши, нажатие, нажатие клавиши) на компьютере в течение x минут. Система становится активной, когда пользователь совершает первое действие: нажимает кнопку мыши, перемещает ее, нажимает клавишу и так далее. Можно ли обнаружить эти неактивные * / * активные состояния с помощью сценария оболочки?
Ионика Бизэу

Ответы:

17

Эта ветка на форумах ArchLinux содержит небольшую программу на C, которая запрашивает у xscreensaver информацию о том, как долго пользователь простаивал, это, похоже, очень близко к вашим требованиям:

#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);
}

Сохраните это как getIdle.cи скомпилируйте с

gcc -o getIdle getIdle.c -lXss -lX11

получить исполняемый файл getIdle. Эта программа печатает «простой» (пользователь не перемещается / не щелкает мышью, не использует клавиатуру) в миллисекундах, поэтому сценарий bash, основанный на этом, может выглядеть следующим образом:

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

Это все еще требует регулярного опроса, но он делает все, что вам нужно ...

Джаспер
источник
Работает как положено! +1
Ионика Бизэу
Вы стоите больше очков!
Ионика Бизэу
2
Вы можете сэкономить, компилируя свою собственную программу и просто используя ее xprintidle, которая доступна в большинстве дистрибутивов и делает то же самое.
Бунт
3

TMOUT в bash завершит интерактивный сеанс через заданное количество секунд. Вы можете использовать этот механизм.

Вы перехватываете выход из системы, устанавливая соответствующую ловушку (я не проверял это) или используя сценарии bash-logout-scripts (~ / .bash_logout).

Вот хороший ответ суперпользователя в этом направлении.

Nils
источник
Это не относится к тому, как пользователь будет выполнять команду вместо выхода из системы по прошествии $TMOUTнескольких секунд.
chepner
Можете ли вы добавить больше информации к вашему ответу? Это все еще неясно для меня ...
Ionică Bizau
@chepner Я добавил некоторые подробности в свой ответ.
Нильс
В любом случае, это просто выводит пользователя из системы после истечения времени. Я не думаю, что есть какой-либо способ прервать журнал, либо из EXITловушки, либо из .bash_logout.
Чепнер
3

Это не совсем то, что вы просили, но всегда есть batch-команда (обычно это специальный вызов at-команды и использование atd-daemon).

batchпозволяет настроить команду для запуска, когда средняя нагрузка падает ниже определенного предела (обычно 1,5, но это можно установить при запуске atd). При atэтом также возможно выполнить работу таким образом, чтобы она не выполнялась в определенное время; задание только что доставлено batchв это время и запускается сначала, когда средняя нагрузка падает (например, она запускается, как только средняя нагрузка падает ниже 1,5 через 2 часа ночи).

К сожалению, пакетное задание будет работать до конца, оно не остановится, если компьютер больше не будет работать.

+++

Если вам нужно пойти по маршруту программирования (как это выглядит из других ответов), я думаю, я бы попытался создать нечто похожее на демоны atdили crond, которые отслеживали бы зарегистрированных пользователей и / или среднюю загрузку. Затем этот демон может запускать скрипты / программы из определенного каталога и запускать / продолжать или останавливать их (с сигналами) по мере необходимости.

Баард Копперуд
источник
Если вы сделали это и использовали .lockфайлы, вы могли бы легко справиться с проблемами синхронизации.
mikeserv
2

В этой теме есть несколько решений, основанных на обнаружении активности клавиатуры и мыши. Я бегу xprintidleот работы cron, которая запускается каждые несколько минут. Но, как они указывают, xprintidleэто не поддерживается, поэтому вы можете установить модуль Perl и использовать его вместо этого:

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

Я бы использовал любое решение путем опроса cron, в сценарии, который выходит вверху, если пользовательский интерфейс не был достаточно простаивает. Конечно, сценарий понадобится для export DISPLAY=:0.0того, чтобы поговорить с X11.

Помните, что ваша клавиатура и мышь могут быть неактивны при просмотре фильма или при выполнении задачи с большой нагрузкой на процессор.

Метаморфические
источник
1

Я не знаю способа сделать это без опроса какой-либо статистики системы, например, в других ответах используется заставка или таймер простоя bash или запуск из .bash_logout, но вот идея проверить загрузку процессора.

Это по-прежнему будет включать опрос каждые n секунд, и если загрузка вашего ЦП будет ниже любой выбранной вами величины, вы можете написать сценарий для любого запуска. Тем не менее, все, что вы запускаете, может увеличить нагрузку на процессор, но вы можете использовать nice на своих «вещах», чтобы не считать их.

Вот тестовый скрипт с использованием top, но вы могли бы вместо этого использовать mpstat или проверить средние значения загрузки?

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

Это всего лишь сценарий, который я написал вместе, чтобы проверить чтение простаивающих сверху. Вы можете разобрать, /proc/statно я думаю, что это показывает только общее время, и вам нужно сравнить результаты за интервал. У меня есть своя собственная проблема (linux mint 16), при первом запуске он, кажется, никогда не меняет cpustats, как будто ему нужно ждать, чтобы разобрать / proc / stat, поэтому top -bn2теоретически это top -bn1должно сработать.

Xen2050
источник
Тьфу ... правда? Опрос статистики процессора?
Рольф
Кстати, вы также можете опросить wкоманду, которая показывает время простоя пользователя. - Между прочим, я не осуждаю, просто для меня я хочу обнаружить холостой ход, чтобы перевести машину в режим сна, сэкономить электроэнергию, и опрос идет против этого.
Рольф
@ Ролф Звучит неплохо, судя по всему ... так как этот комментарий на самом деле ничего не добавляет, его, вероятно, следует удалить, да? В любом случае, другие ответы используют простой несколькими различными способами, но как вы можете обнаружить простой, не глядя на систему и не спрашивая ее?
Xen2050