如果 Linux 空闲 5 分钟则执行一条命令

如果 Linux 空闲 5 分钟则执行一条命令

我想执行如下命令

 notify-send 'a'

如果我的 Linux 机器已经闲置了 5 分钟。

我所说的空闲,与激活的屏幕保护程序所定义的“空闲”是同一个意思。

答案1

xprintidle我使用一个名为“找出 X 空闲时间”的程序,我强烈猜测它使用与屏幕保护程序相同的数据源。xprintidle似乎不再有上游,但是Debian 软件包活得好好的。

这是一个非常简单的应用程序:它返回自上次 X 交互以来的毫秒数:

$ sleep 1 && xprintidle
940
$ sleep 5 && xprintidle
4916
$ sleep 10 && xprintidle
9932

(注意:由于底层系统,它将始终给出一个略低于“实际”空闲时间的毫秒值)。

您可以使用它来创建一个脚本,该脚本在空闲时间五分钟后按照特定顺序运行,例如:

#!/bin/sh

# Wanted trigger timeout in milliseconds.
IDLE_TIME=$((5*60*1000))

# Sequence to execute when timeout triggers.
trigger_cmd() {
    echo "Triggered action $(date)"
}

sleep_time=$IDLE_TIME
triggered=false

# ceil() instead of floor()
while sleep $(((sleep_time+999)/1000)); do
    idle=$(xprintidle)
    if [ $idle -ge $IDLE_TIME ]; then
        if ! $triggered; then
            trigger_cmd
            triggered=true
            sleep_time=$IDLE_TIME
        fi
    else
        triggered=false
        # Give 100 ms buffer to avoid frantic loops shortly before triggers.
        sleep_time=$((IDLE_TIME-idle+100))
    fi
done

100 毫秒的偏移量是因为之前提到的怪癖,xprintidle当像这样执行时,它总是会返回比“实际”空闲时间略低的时间。它在没有这个偏移量的情况下也能工作,然后会更精确到十分之一秒,但它会xprintidle在间隔结束前的最后几毫秒内疯狂地触发检查。这不会占用任何性能,但我觉得这不太优雅。

我已经在 Perl 脚本(irssi 插件)中使用类似的方法很长一段时间了,但上述内容只是编写的,除了在编写过程中进行了几次试运行外,尚未真正进行过测试。

通过在 X 中的终端中运行它来尝试它。我建议将超时设置为例如 5000 毫秒进行测试,并set -x直接在下面添加#!/bin/sh以获取信息输出来查看其工作原理。

答案2

我用它xssstate来做这样的事情。它的suckless-tools包装在Debian或者Ubuntu, 或者上游

然后你可以使用下面的 shell 脚本:

#!/bin/sh

if [ $# -lt 2 ];
then
    printf "usage: %s minutes command\n" "$(basename $0)" 2>&1
    exit 1
fi

timeout=$(($1*60*1000))
shift
cmd="$@"
triggered=false

while true
do
    tosleep=$(((timeout - $(xssstate -i)) / 1000))
    if [ $tosleep -le 0 ];
    then
        $triggered || $cmd
        triggered=true
    else
        triggered=false
        sleep $tosleep
    fi
done

答案3

如果你使用GNOME Shell,你可以使用 Mutter 显示管理器查询用户会话不活动状态gdbus,无需任何第三方实用程序。

例如:

# polling interval in seconds
polling_interval=10

# timeout in milliseconds
timeout=300000

while true; do

  inactivity=`gdbus call --session \
             --dest org.gnome.Shell \
             --object-path /org/gnome/Mutter/IdleMonitor/Core \
             --method org.gnome.Mutter.IdleMonitor.GetIdletime \
             | grep -oP '^(\(uint64\s*)\K\d+'`

  if [[ $timeout -lt $inactivity ]] ; then
    notify-send 'a'
  fi

  sleep $polling_interval
  
done

答案4

bsd ports(软件包集合)有一个程序可以做到这一点:
http://man.openbsd.org/OpenBSD-current/man1/xidle.1
例如可以在这里获取:
http://distcache.freebsd.org/local-distfiles/novel/xidle-26052015.tar.bz2

构建如下:

 # apt-get install libxss-dev # for include/X11/extensions/scrnsaver.h
 # gcc -o /usr/local/bin/xidle xidle.c -lX11 -lXss

请注意,-program 需要包含二进制文件的完整路径,因为它被传递给 execv()。

$ xidle -timeout 120 -program "/usr/bin/xlock -mode pyro"  

相关内容