비활성 기간과 해당 기간이 완료된 후 특정 스크립트를 실행하는 방법을 찾고 있습니다. '비활성'이란 마우스 및 키보드 이벤트가 부족함을 의미합니다. 예: 내가 원하는 것:
X분 후에 첫 번째 스크립트를 실행합니다. 비활동성;
마우스나 키보드로 해당 기간이 중단되면 두 번째 스크립트를 실행합니다.
해당 메소드가 X 시스템에 연결되지 않고 터미널(X가 시작되지 않은 경우)에서도 작동하는 것이 가장 좋습니다.
답변1
약간의 C 마법을 사용하면 이 작업을 수행할 수 있습니다(필요한 기능을 지원하는 다른 프로그래밍 언어도 괜찮습니다). 당신이 해야 할 일은 다음과 같습니다:
- 모든
input
이벤트 장치 열기(일치하는 모든 것/dev/input/event[0-9]*
) - 해당 장치를 호출하고
select(2)
적절한 시간 초과(유휴 기간)로 입력을 기다리고 있습니다.- 시간 초과 시: 아무 일도 일어나지 않았습니다: 프로그램을 시작하세요
- 입력이 준비되면: 무슨 일이 일어났습니다: 실행 중인 경우 프로그램을 종료합니다.
read(2)
모든 장치에서 입력되므로 다음select(2)
호출이 즉시 반환되지 않습니다.
C의 간단한 예는 다음과 같습니다.
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
int *fds, ret, i;
glob_t glob_result;
/* find all devices matching /dev/input/event[0-9]* */
ret = glob("/dev/input/event[0-9]*", GLOB_ERR|GLOB_NOSORT|GLOB_NOESCAPE, NULL, &glob_result);
if (ret)
err(EXIT_FAILURE, "glob");
/* allocate array for opened file descriptors */
fds = malloc(sizeof(*fds) * (glob_result.gl_pathc+1));
if (fds == NULL)
err(EXIT_FAILURE, "malloc");
/* open devices */
for (i = 0; i < glob_result.gl_pathc; i++) {
fds[i] = open(glob_result.gl_pathv[i], O_RDONLY|O_NONBLOCK);
if (fds[i] == -1)
err(EXIT_FAILURE, "open `%s'", glob_result.gl_pathv[i]);
}
fds[i] = -1; /* end of array */
for (;;) {
char buf[512];
struct timeval timeout;
fd_set readfds;
int nfds = -1;
FD_ZERO(&readfds);
/* select(2) might alter the fdset, thus freshly set it
on every iteration */
for (i = 0; fds[i] != -1; i++) {
FD_SET(fds[i], &readfds);
nfds = fds[i] >= nfds ? fds[i] + 1 : nfds;
/* read everything what's available on this fd */
while ((ret = read(fds[i], buf, sizeof(buf))) > 0)
continue; /* read away input */
if (ret == -1 && errno != EAGAIN)
err(EXIT_FAILURE, "read");
}
/* same for timeout, 5 seconds here */
timeout.tv_sec = 5; /* FIXME */
timeout.tv_usec = 0;
ret = select(nfds, &readfds, NULL, NULL, &timeout);
if (ret == -1)
err(EXIT_FAILURE, "select");
if (ret == 0)
printf("Timeout: start first script\n");
} else {
printf("No timeout: start second script\n");
}
}
return 0;
}
이 예에서는 입력을 무기한으로 기다립니다. 5초 후에 입력이 수신되지 않으면 "Timeout: …"이 인쇄되고, 입력이 수신되면 "No timeout: …"이 인쇄됩니다.
자세한 내용은(프로세스를 실행하고 종료하려는 경우) 각각 및를 fork(2)
참조 하세요 . 앞서 언급했듯이 파일에서 실행할 수 있는 모든 언어이면 충분하므로 Python이나 Ruby 등에서 실행할 수도 있습니다.exec(2)
kill(2)
select(2)
메모: 이는 단지 예시일 뿐, 추가적으로 처리해야 할 사항이 있을 수 있습니다. 예를 들어 "Timeout"이 인쇄됩니다.모든5초, 입력이 수신될 때까지 한 번만 발생하지 않고 마찬가지로 "No timeout"이 켜집니다.모든키 입력/마우스 이동.
또한 이벤트 장치는 명백한 이유로 누구도 읽을 수 없기 root
때문에 로 실행해야 합니다 .input
답변2
여기 당신이 컴파일할 수 있는 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
이 실행 파일을 사용하면 유휴 시간이 얼마나 지났는지 알 수 있는 스크립트를 구성할 수 있습니다. #1의 시간 창과 같으면 첫 번째 스크립트를 실행하세요. 유휴 창이 중단되면(질문의 글머리 기호 #2) 두 번째 스크립트를 실행하세요.
작은 예
아래는 5초가 지났을 때 최소한 수표의 첫 번째 부분을 구성할 수 있는 방법을 보여줍니다.
$ 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
위에서는 5초 이상 마우스를 움직이거나 키를 누르지 않았습니다. 그런 다음 키를 누르면 Shift루프가 다시 still < 5
.