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

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

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

echo "You started to be inactive."

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

echo "You started to be active, again."

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

答案1

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

这仍然需要定期轮询,但它可以满足您所需的一切......

答案2

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

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

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

+++

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

答案3

bash 中的 TMOUT 将在设定的秒数后终止交互式会话。您可以使用该机制。

您可以通过设置相应的陷阱(我没有测试)或使用 bash-logout-scripts (~/.bash_logout) 来捕获注销。

这是一个很好的超级用户答案。

答案4

我不知道有什么方法可以在不轮询某种系统统计信息的情况下执行此操作,就像其他答案使用屏幕保护程序或 bash 空闲计时器,或者从 .bash_logout 运行一样,但这里有一个检查 CPU 使用情况的想法。

这仍然涉及每 n 秒轮询一次,如果您的 CPU 使用率低于您选择的任何数量,那么您可以编写您想要运行的任何脚本。然而,无论你运行什么,都可能会增加 CPU 使用率,但你可以在你的“东西”上使用 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但我认为它只显示总时间,并且您需要比较一个时间间隔内的结果。 Top 对我来说有它自己的问题(linux mint 16),在第一次运行时它似乎永远不会改变 cpustats,就好像它必须等待解析 /proc/stat 本身一样,因此理论上top -bn2应该top -bn1可以工作。

相关内容