在系统空闲和再次活动时运行命令

Ion*_*zău 21 linux shell bash

我想在用户变为非活动状态(系统空闲)时运行命令。例如:

echo "You started to be inactive."
Run Code Online (Sandbox Code Playgroud)

此外,当用户再次活跃时(系统不再空闲):

echo "You started to be active, again."
Run Code Online (Sandbox Code Playgroud)

我需要一个可以执行此操作的 shell 脚本。如果没有计时器/间隔,这可能吗?也许是一些系统事件?

Jas*_*per 22

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);
}
Run Code Online (Sandbox Code Playgroud)

将其另存为getIdle.c并编译

gcc -o getIdle getIdle.c -lXss -lX11
Run Code Online (Sandbox Code Playgroud)

得到一个可执行文件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
Run Code Online (Sandbox Code Playgroud)

这仍然需要定期轮询,但它可以完成您需要的一切......

  • 您可以节省自己编译自己的程序,而只需使用`xprintidle`,它在大多数发行版中都可用,并且可以完成完全相同的事情。 (6认同)

Baa*_*rud 5

这并不完全是您所要求的,但总是有batch- 命令(通常是 - 命令的特殊调用at并使用atd- 守护进程)。

batch允许您在平均负载低于某个限制(通常为 1.5,但这可以在启动时设置atd)时提示要运行的命令。还可以以at这样的方式提示作业,而不是在某个特定时间运行;该作业只是batch在那时交付,并在平均负载下降时首次运行(例如,一旦凌晨 2:00 后的某个时间平均负载下降到 1.5 以下,它就会运行)。

不幸的是,批处理作业将运行到最后,如果计算机不再空闲,它也不会停止。

+++

如果您必须走编程路线(从其他答案看来是这样),我想我会尝试制作类似于atdcrond守护进程的东西,来监视登录用户和/或平均负载。然后,该守护进程可以从某个目录运行脚本/程序,并根据需要启动/继续或停止它们(使用信号)。