![일정 기간 동안 활동이 없으면 스크립트 실행](https://linux55.com/image/36384/%EC%9D%BC%EC%A0%95%20%EA%B8%B0%EA%B0%84%20%EB%8F%99%EC%95%88%20%ED%99%9C%EB%8F%99%EC%9D%B4%20%EC%97%86%EC%9C%BC%EB%A9%B4%20%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%20%EC%8B%A4%ED%96%89.png)
일정 기간 동안 활동하지 않고 해당 기간이 끝난 후에 특정 스크립트를 실행할 수 있는 방법을 찾고 있습니다. "비활성"이란 마우스 및 키보드 이벤트가 없다는 의미입니다. 예를 들어 나는 다음을 원한다:
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초, 입력이 수신될 때까지 한 번이 아니라 "시간 초과 없음"도 나타납니다.모든키 입력/마우스 이동.
또한 이벤트 장치는 명백한 이유로 누구도 읽을 수 없으므로 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
.