Как мне вернуть приглашение при запуске `at 'из терминала

Вы можете сделать это с помощью небольшой магии Си (подойдет и любой другой язык программирования, поддерживающий необходимые функции). Что вам нужно сделать, это:

  • открыть все 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 секунд ввод не будет получен, будет напечатано «Тайм-аут:…», если ввод будет получен «Нет тайм-аута:…»

Для дальнейшего чтения (однако вы хотите выполнить и завершить процессы) см. fork (2) , exec (2) и kill (2) соответственно.Как упоминалось ранее, каждого языка, позволяющего запускать select (2) для файлов, будет достаточно, так что вы также можете использовать Python, Ruby или что-то подобное.

Примечание: Это всего лишь пример, нужно позаботиться о дополнительных вещах. Например, это печатает «Тайм-аут» каждые 5 секунд, а не только один раз, пока не будет получен ввод, аналогично «Нет тайм-аута» появляется каждый нажатие клавиши / движение мыши.

Кроме того, это нужно будет запускать от имени root , поскольку устройства событий ввода никому не доступны для чтения по очевидным причинам.

1
09.03.2019, 03:01
1 ответ

Вы успешно отправили задание at, и оно успешно распечатало дату на (ваш )терминал в /dev/pts/9. У вас также есть оболочка, которая напечатала приглашение и должным образом ожидает вашего ввода.

Это симуляция того, что произошло:

your-prompt-here$ at -f './at-test.sh' now + 1 minutes
job 1 at Fri Mar  8 20:13:00 2019
your-prompt-here$ 

...проходит одна минута; возобновить демонстрацию

your-prompt-here$ 20:14:1552093897
echo I am still here
I am still here
your-prompt-here$

Как видите, моя оболочка приняла команду echo; мой курсор просто не был там, где я «ожидал», потому что задание atнацарапало мой терминал.

2
27.01.2020, 23:30

Теги

Похожие вопросы