Run a command when system is idle and when is active again

This thread on the ArchLinux forums contains a short C program that queries the xscreensaver for information how long the user has been idle, this seems to be quite close to your requirements:

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

Save this as getIdle.c and compile with

gcc -o getIdle getIdle.c -lXss -lX11

to get an executable file getIdle. This program prints the "idle time" (user does not move/click with mouse, does not use keyboard) in milliseconds, so a bash script that builds upon this could looke like this:

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

This still needs regular polling, but it does everything you need...


TMOUT in bash will terminate an interactive session after the set number of seconds. You may use that mechanism.

You migth capture the logout by setting an according trap (I did not test that), or by using the bash-logout-scripts (~/.bash_logout).

Here is a good superuser-answer into that direction.


This is not quite what you asked for, but there is always the batch-command (usually a special invocation of the at-command and using the atd-daemon).

batch lets you cue-up a command to be run when the load-average drop below a certain limit (usually 1.5, but this can be set when starting atd). With at it's also possible to cue a job in such a way that rather than being run at a certain time; the job is just delivered to batchat that time, and first run when the load-average drops (eg. it's run as soon as the load-average drops under 1.5 sometime after 2:00am).

Unfortunately a batch-job will then run to it's end, it will not stop if the computer is no-longer idle.

+++

If you have to go the programming-route (which it looks like from the other answers), I think I'd try to make something similar to the atd or crond daemons, that monitored logged-in users and/or load-average. This daemon could then run scripts/programs from a certain directory, and start/continue or stop them (with signals) as needed be.

Tags:

Linux

Shell

Bash