次のようなコマンドを実行したい
notify-send 'a'
linuxマシンが5分間アイドル状態の場合。
アイドルとは、アクティブ化されたスクリーンセーバーが「アイドル」を定義するために使用するのと同じことを意味します。
私はxprintidle
と呼ばれるプログラムを使用してXアイドル時間を調べます。これはスクリーンセーバーと同じデータソースを使用していると強く推測しています。 xprintidle
はもはやアップストリームを持っているようには見えませんが、 Debianパッケージ は健在です。
これは非常に単純なアプリケーションです。最後のXインタラクションからのミリ秒数を返します。
$ sleep 1 && xprintidle
940
$ sleep 5 && xprintidle
4916
$ sleep 10 && xprintidle
9932
(注:基盤となるシステムにより、「実際の」アイドル時間よりもわずかに短い値が一貫してmsで提供されます)。
これを使用して、次のようにアイドル時間の5分後に特定のシーケンスを実行するスクリプトを作成できます。
#!/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
が常に「実際の」アイドル時間よりもわずかに短い時間を返すという前述の癖のためです。このオフセットなしで機能し、1/10秒までより正確になりますが、インターバルが終了する前の最後のミリ秒の間にxprintidle
チェックを必死にトリガーします。決してパフォーマンスの独り占めではありませんが、私はそれが優雅でないと思います。
私はかなり前からPerlスクリプト(irssiプラグイン)で同様のアプローチを使用してきましたが、上記は単に作成されただけであり、作成中のいくつかのトライアル実行を除いて実際にはテストされていません。
X内のターミナルで実行してみてください。タイムアウトを次のように設定することをお勧めします。テストに5000ミリ秒、set -x
のすぐ下#!/bin/sh
は、それがどのように機能するかを確認するための有益な出力を取得します。
私はそのような目的でxssstate
を使用しています。 suckless-tools
Debian または bunt 、または pstream のパッケージ。
その後、次のシェルスクリプトを使用できます。
#!/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
これが、コンパイルできるCアプリケーションです。
$ more xidle.c
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/scrnsaver.h>
/* Report amount of X server idle time. */
/* Build with- */
/* cc xidle.c -o xidle -lX11 -lXext -lXss */
int main(int argc, char *argv[])
{
Display *display;
int event_base, error_base;
XScreenSaverInfo info;
float seconds;
display = XOpenDisplay("");
if (XScreenSaverQueryExtension(display, &event_base, &error_base)) {
XScreenSaverQueryInfo(display, DefaultRootWindow(display), &info);
seconds = (float)info.idle/1000.0f;
printf("%f\n",seconds);
return(0);
}
else {
fprintf(stderr,"Error: XScreenSaver Extension not present\n");
return(1);
}
}
ビルドするにはいくつかのライブラリが必要です。私のFedora 19システムでは、次のライブラリが必要でした。
$ rpm -qf /lib64/libX11.so.6 /lib64/libXext.so.6 /lib64/libXss.so.1
libX11-1.6.0-1.fc19.x86_64
libXext-1.3.2-1.fc19.x86_64
libXScrnSaver-1.2.2-5.fc19.x86_64
これらがインストールされたら、上記のようにコンパイルしました:
$ gcc xidle.c -o xidle -lX11 -lXext -lXss
次のように実行すると、Xがアイドル時間として検出している秒数を報告できることがわかります。
$ while [ 1 ]; do ./xidle ; sleep 2;done
0.005000
1.948000
3.954000
5.959000
7.965000
0.073000 <--- moved the mouse here which resets it
0.035000
この実行可能ファイルを使用して、xidle
によって報告されたアイドル時間を監視しながら、このようなことを実行できるスクリプトを作成できます。
$ while [ 1 ]; do idle=$(./xidle);
[ $( echo "$idle > 5" | bc ) -eq 0 ] && echo "still < 5" || echo "now > 5";
sleep 2;
done
still < 5
still < 5
still < 5
now > 5
now > 5
still < 5
still < 5
still < 5
上記は、アイドル時間が5秒経過するまでstill < 5
を示しています。この時間が経過すると、now > 5
と表示され始めます。つまり、5秒以上経過しています。
注:上記の例にnotify-send 'a'
を組み込むことができます。