Как приостановить команду при выводе некоторой строки?

возможно, вам просто нужно сделать:

stty sane

Я заметил, что на странице forkpty() man сказано, что он скопирует настройки termios из *termp на вновь открытый pty, но не сказано, что он делает с ними в противном случае, и единственный не-NULL аргумент, который вы передаете forkpty() - для главного fd pty. Я бы предположил, что в итоге вы получите полностью NULL-структуру termios, что не может быть очень полезным. Это не будет беспокоить bash, который имеет readline() для обработки всех своих собственных терминальных вещей, и поэтому он будет интерпретировать все символы по умолчанию, так или иначе.

вот цитата из довольно информативной статьи на эту тему:

опция -F программы stty может быть полезна для подглядывания за тем, что другая программа делает с терминалом. Если вы запустите tty в оболочке, она выведет путь к терминальному устройству этой оболочки (обычно в виде /dev/pts/N, по крайней мере, в Linux). Теперь, из другой оболочки, вы можете запустить stty -a -F /dev/pts/N, чтобы увидеть, как настроен терминал первой оболочки. Затем можно запустить программы в первой оболочке и повторить команду stty во второй оболочке, чтобы увидеть, какие настройки установлены. Например, если я запущу stty -F /dev/pts/10 прямо сейчас (в то время как у меня bash разговаривает с gnome-terminal через этот pty), я увижу:

    $ stty -F /dev/pts/10
      speed 38400 baud; line = 0;
      eol = M-^?; eol2 = M-^?; swtch = M-^?; lnext = ; min = 1; time = 0;
     -icrnl iutf8
     -icanon -echo

Итак, мы видим, что bash/readline отключил CR→LF перевод на входе (icrnl), отключил canonical режим и echo, но включил режим UTF-8 (потому что bash обнаружил локаль utf-8). Обратите внимание, что если я запускаю stty непосредственно в этой оболочке, я вижу нечто несколько иное:

     $ stty
       speed 38400 baud; line = 0;
       eol = M-^?; eol2 = M-^?; swtch = M-^?;
       iutf8

Это происходит потому, что bash поддерживает свой собственный набор termios настроек (для readline), и сохраняет и восстанавливает настройки во время работы программ, так что настройки, установленные во время работы программы, отличаются от настроек, установленных во время ввода текста в приглашении bash.

1
13.07.2018, 13:38
2 ответа
%./mystery
a
b
c
% 

Можно подать сигнал STOPпрограмме, а затем CONTпродолжить ее выполнение; следующий код TCL ожидает появления bна выходе и в этот момент останавливает процесс, который должен оставаться остановленным до тех пор, пока пользователь не введет строку для expect_user, чтобы воздействовать на (как минимум на новую строку ).

#!/usr/bin/env expect
spawn -noecho./mystery
set spid [exp_pid]
expect -ex b { exec kill -STOP $spid; send_user "STOP\n" }
expect_user -re. { exec kill -CONT $spid }
expect eof

Это, конечно, имеет всевозможные проблемы, например, если mysteryработает слишком быстро, или если вывод буферизуется и т. д. Мне пришлось замедлить C и отключить буферизацию, чтобы это сработало:

% cat mystery.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
    setvbuf(stdout, (char *) NULL, _IONBF, (size_t) 0);
    printf("a\n");
    sleep(1);
    printf("b\n");
    sleep(1);
    printf("c\n");
    return 0;
}

Программой на C можно лучше управлять, запуская ее под отладчиком, таким как gdb;точки останова были бы гораздо более точным способом остановить выполнение в определенной точке кода, чем реагировать на ввод-вывод. Символы отладки помогут, но не обязательны:

% gdb mystery
Reading symbols from mystery...(no debugging symbols found)...done.
(gdb) quit
% otool -dtv mystery | grep callq
0000000100000f26        callq   0x100000f70
0000000100000f32        callq   0x100000f6a
0000000100000f3c        callq   0x100000f76
0000000100000f48        callq   0x100000f6a
0000000100000f52        callq   0x100000f76
0000000100000f5e        callq   0x100000f6a

Так что на самом деле это на Mac (разборка зависит от платформы ). Выше приведены вызовы setvbuf, printfи sleep, поэтому с начальным адресом

% otool -dtv mystery | sed 3q
mystery:
_main:
0000000100000f06        pushq   %rbp
% perl -E 'say 0x0000000100000f52 - 0x0000000100000f06'
76
% gdb mystery
Reading symbols from mystery...(no debugging symbols found)...done.
(gdb) b *main + 76
Breakpoint 1 at 0x100000f52
(gdb) r
Starting program: /Users/jhqdoe/tmp/mystery
a
b

Breakpoint 1, 0x0000000100000f52 in main ()
(gdb) 

И тогда вы можете делать все, что необходимо, и продолжать программу по своему усмотрению.

Другой идеей было бы использовать LD_PRELOADдля настройки поведения программы, предполагая, конечно, что наиболее разумный вариант — перекомпилировать программу из исходного кода — невозможен. Еще одним вариантом было бы исправить двоичный файл C, чтобы он вел себя как нужно .

2
27.01.2020, 23:32

Вы можете использовать read, который ожидает ввода пользователем, прежде чем продолжить

Пример:

Эта программа запускает цикл и выводит вывод ls -lhtr, ожидает ввода пользователя (Нажмите клавишу ввода или любой другой символ ), а затем снова выводит вывод и продолжает процесс в бесконечном цикле

#!/bin/bash

while (true); do
        ls -lhtr;
        read i;
done

Таким образом, в основном вместо ls -lhtrвы можете использовать команду, выходные данные которой вам нужно отслеживать, после того, как вы закончите изменение среды и файлов, вы можете нажать любую клавишу, чтобы снова продолжить мониторинг вывода команды

0
27.01.2020, 23:32

Теги

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