Захват STDIN / STDERR / STDOUT процесса ПОСЛЕ его запуска с помощью командной строки?

Спасибо! Мой пользовательский случай: я начал длительный интерактивный процесс «настройки» (скажем, под «экраном»), а затем понял, что мне нужно всегда отвечать «нет», пока я не увижу определенное ключевое слово. Кажется пустой тратой времени делать это вручную (не говоря уже о том, что я могу легко пропустить ключевое слово..)

Таким образом, кажется, я хочу направить (копию) STDERR / STDOUT в фильтр, а также иметь возможность вводить в STDIN (консольного) процесса ПОСЛЕ его запуска с помощью командной строки? Есть готовое решение?

Следующие инструменты кажутся полезными. Для захвата вывода используйте

strace -ewrite -p $PID

Это не так чисто (показывает строки вроде: write(#,) ), но работает! Но правильно ли он обрабатывает UTF8?

Чтобы перенаправить вывод, сделайте что-то вроде

printf '..input..' >/dev/pts/33

Но непонятно как найти нужное устройство..


person John Quilder    schedule 28.01.2012    source источник
comment
Вы должны добавить свое решение в качестве ответа и принять его.   -  person Daenyth    schedule 31.01.2012


Ответы (3)


Решено в Linux (по-видимому, для Linux):

reptyr -s PID 

прикрепляет процесс к другому терминалу и/или предоставляет его ввод и вывод в виде каналов.

person John Quilder    schedule 04.02.2012

Это возможно, но это некрасиво. Процесс выглядит следующим образом:

  1. используйте gdb для подключения к уже запущенному процессу
  2. запустите p close(<fd>), где <fd> — дескриптор файла, который вы хотите изменить
  3. запустить p creat("<path to file">, <perms>), чтобы отправить вывод закрытого fd куда-то еще

См. эту ссылку для более подробная информация

person SiegeX    schedule 28.01.2012
comment
Вместо close() для fd вы можете сначала создать новый fd (creat(), open() и т. д.), затем использовать dup2() для замены fd, который вы хотите захватить, а затем close() новый fd. Причина в том, что open() и т. д. всегда будет давать самый низкий доступный fd, поэтому, если вы закроете fd и откроете его сразу после этого, нет никакой гарантии, что вы получите тот же fd. Возможно, это не так важно для stdin/stdout/stderr, потому что они fd 0,1,2, но в общем случае стоит упомянуть. - person FatalError; 29.01.2012
comment
маленькая программа reptyr -s PID делает именно это - person John Quilder; 31.01.2012

Почему ты хочешь это сделать??

Портативным способом Posix это невозможно! Возможно, open-обработка псевдофайлов /proc/1234/fd/0, /proc/1234/fd/1 и /proc/1234/fd/3 (для процесса 1234) может быть ужасной возможностью! И даже это может не работать в некоторых случаях (например, для труб).

В частности, я считаю, что семантика SIGPIPE, отправляемая процессу, если никто не читает канал, будет нарушена...

И я не верю, что вы сможете сохранить качество псевдотерминала, например. стандартный вывод .

Так что, по сути, вам лучше найти другой способ достижения ваших общих целей, который вы не объяснили явно.

Если ваш прецедент представляет собой какой-то странный скрипт configure, вы можете перезапустить его и добавить какой-нибудь собственный скрипт (в оболочке, python, perl и т. д.). Не теряйте времени, пытаясь поймать существующий configure процесс, просто перезапустите его соответствующим образом.

Посмотрите также на команду screen (и как она реализована!)

person Basile Starynkevitch    schedule 28.01.2012
comment
Спасибо! Мой пользовательский случай: я начал длительный интерактивный процесс «настройки» (скажем, под «экраном»), а затем понял, что мне нужно ответить «нет». - person John Quilder; 30.01.2012
comment
Спасибо! Мой пользовательский случай: я начал длительный интерактивный процесс «настройки» (скажем, под «экраном»), а затем понял, что мне нужно всегда отвечать «нет», пока я не увижу определенное ключевое слово. Кажется пустой тратой времени делать это вручную (не говоря уже о том, что я могу легко пропустить ключевое слово..) - person John Quilder; 30.01.2012
comment
Спасибо еще раз! Я хочу сказать, что иногда было бы очень удобно иметь возможность сделать это с любым процессом; 'configure' - это только пример... 'screen' может делать что-то подобное, но не совсем: вы можете фильтровать ( :exec !..| less ) либо ввод, либо вывод, но не оба. Кажется, тогда я должен написать свой собственный сценарий. - person John Quilder; 30.01.2012
comment
Если вы сочтете это удобным (а я нет), рассмотрите возможность внесения в ядро ​​Linux некоторых новых системных вызовов для его реализации. Затем измените оболочки для этого. Участвуйте в движении за свободное программное обеспечение! - person Basile Starynkevitch; 30.01.2012
comment
Basile, мой вопрос решен: reptyr -s PID делает то, что я хочу, и кажется достаточно надежным. - person John Quilder; 31.01.2012