비활성 기간 후 스크립트 실행

비활성 기간 후 스크립트 실행

비활성 기간과 해당 기간이 완료된 후 특정 스크립트를 실행하는 방법을 찾고 있습니다. '비활성'이란 마우스 및 키보드 이벤트가 부족함을 의미합니다. 예: 내가 원하는 것:

  1. X분 후에 첫 번째 스크립트를 실행합니다. 비활동성;

  2. 마우스나 키보드로 해당 기간이 중단되면 두 번째 스크립트를 실행합니다.

해당 메소드가 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.

참고자료

관련 정보