Текст от стандартного ввода, не виденный после выхода из программы из readline

На этот вопрос нет простого ответа, у вас есть следующие вещи:

Inotify

Вы можете использовать inotify чтобы получать уведомления всякий раз, когда что-то меняет файл. inotify сам по себе не является утилитой, это интерфейс, предоставляемый ядром Linux, но есть такие утилиты, как, например, inotifywait из пакета inotify-tools .

Проблема с inotify заключается в том, что он не сообщает вам, какой процесс изменил файл.

Пример:

mst@mst-nb1:~$ inotifywait 123
Setting up watches.
Watches established.    # now i write to "123" in another terminal
123 MODIFY 

lsof

Одна действительно замечательная утилита для определения того, какой процесс держит файл открытым, - это lsof . Например, выполнив lsof / var / log / syslog , вы можете увидеть, какие процессы в настоящее время держат этот файл открытым.

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

Причина, по которой lsof не может отслеживать файл так же, как inotify , заключается в том, что он получает информацию, просто просматривая / proc файловая система, но не устанавливает никаких наблюдателей.

Пример:

# Terminal 1 (I open the file)
mst@mst-nb1:~$ cat > 123

# Terminal 2
mst@mst-nb1:~$ lsof 123
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
cat     24097  mst    1w   REG  252,1        0 16791997 123

loggedfs

Это может быть вашим лучшим шансом, но для его работы требуются некоторые усилия. Вы можете использовать fuse loggedfs и смонтировать его в каталог, где находится ваш файл журнала. Затем он должен предоставить вам подробную информацию о том, что и когда открывает файл.

Единственная проблема с loggedfs заключается в том, что им не так просто пользоваться, как какой-нибудь простой утилитой командной строки.

Если вы хотите разобраться с loggedfs , вы можете обратиться к документации

Заключение

Вывод: у вас есть разные возможности, но нет простой способ.

0
31.01.2019, 08:49
2 ответа

Современные оболочки имеют тенденцию восстанавливать терминальное состояние после выхода из программы; Как вы заметили, более старые или менее способные оболочки могут не работать. Обычный подход, который можно увидеть в APUE и других текстах, состоит в том, чтобы сохранить копию состояния терминала, используя tcgetattr, а затем восстановить это состояние при выходе из программы :

.
#include <sys/time.h>

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>

#include <readline/readline.h>
#include <readline/history.h>

struct itimerval Alarm_Timer;
struct termios Original_Termios;
int Need_Reset;

void sigalrm_handler(int arg)
{
    if (Need_Reset)
        tcsetattr(STDIN_FILENO, TCSANOW, &Original_Termios);
    exit(0);
}

int main(void)
{
    char *line;

    tcgetattr(STDIN_FILENO, &Original_Termios);
    Need_Reset = 1;

    signal(SIGALRM, sigalrm_handler);
    Alarm_Timer.it_value.tv_sec = 3;
    setitimer(ITIMER_REAL, &Alarm_Timer, NULL);

    line = readline("* ");

    if (Need_Reset)
        tcsetattr(STDIN_FILENO, TCSANOW, &Original_Termios);

    exit(0);
}
0
28.01.2020, 05:05

Во-первых, libreadlineустанавливает свои собственные обработчики сигналов для ALRM, INTи т. д. и завершится нормально (после восстановления настроек termios/stty )при получении такого сигнала.

Вы можете проверить, запустив/отследив простую программу, подобную этой:

#include <readline/readline.h>
#include <unistd.h>

int main(void){
        alarm(3); readline("foo> ");
}

Таким образом, вы можете просто избавиться от своего обработчика сигнала.

Во-вторых, вы никогда не должны вызывать exit(3)из обработчика сигнала. exit(3), в отличие от системного вызова _exit(2), не является безопасным для сигналов, главным образом потому, что он должен запускать обработчики, зарегистрированные с помощью atexit(3). Например, просто подумайте, что произойдет, если exit(3)вызывается, когда другой exit(3)уже проходит через эти обработчики.

Если вместо использования readline(3)вы используете свой собственный код, который переводит терминал в необработанный режим и т. д., вы всегда должны сохранять состояние терминала при запуске и при получении SIGCONTи восстановить его перед выходом из и при получении сигнала SIGTSTP. Не только при запуске/выходе, как видно во многих примерах. И если вы используете адресацию курсора, вы также должны включать/выключать ca_modeс экранами smcup/ rmcupпри сохранении/восстановлении настроек termios.

0
28.01.2020, 05:05

Теги

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