Как процесс может перехватывать stdout и stderr другого процесса в Linux?

StackOverflow https://stackoverflow.com/questions/249703

  •  05-07-2019
  •  | 
  •  

Вопрос

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

Есть ли какой-нибудь способ, которым я могу понять, что они пишут в stdout и stderr в удобочитаемом виде?

Я пытался, например, сделать

tail -f /proc/(pid)/fd/1

но на самом деле это не работает.В любом случае, это был рискованный шаг.

Есть еще какие - нибудь идеи ?strace сам по себе довольно многословен и нечитабелен, чтобы увидеть это.

Примечание:Я такой и есть Только заинтересованы в их результатах, а не в чем-либо другом.Во всем остальном я способен разобраться самостоятельно;этот вопрос направлен только на получение доступа к stdout и stderr запущенного процесса после начинаю это делать.

Это было полезно?

Решение

Я не уверен, что это сработает для вас, но я недавно прочитал страницу с описанием , использующий gdb

Другие советы

Поскольку мне не разрешено редактировать ответ Jauco, я дам полный ответ, который сработал для меня (страница Рассела полагается на негарантированное поведение, которое, если вы закроете fd 1 для stdout, следующий вызов создания откроет fd 1 .

Итак, запустите простой бесконечный скрипт, подобный этому:

import time

while True:
    print 'test'
    time.sleep(1)

Сохраните его в test.py, запустите с помощью

python test.py

Получить pid.

ps auxw | grep test.py

Теперь присоедините gdb:

gdb -p (pid)

и сделай волшебство FD:

(gdb) call creat("/tmp/stdout", 0600)
$1 = 3
(gdb) call dup2(3, 1)
$2 = 1

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

Есть несколько новых утилит, которые заключают в себе метод "gdb" и добавить несколько дополнительных штрихов. Тот, который я сейчас использую, называется «reptyr». (& Quot; Re-PTY-эр & Quot;). Помимо захвата STDERR / STDOUT, он фактически изменит управляющий терминал процесса (даже если он ранее не был подключен к терминалу).

Лучшее использование этого - запустить сеанс экрана и использовать его для повторного присоединения запущенного процесса к терминалу на экране, чтобы вы могли безопасно отсоединиться от него и вернуться позже.

Он упакован в популярные дистрибутивы (например: 'apt-get install reptyr').

http://onethingwell.org/post/2924103615/reptyr

Метод GDB кажется лучше, но вы можете сделать это и с помощью strace:

strace -p -e write = 1 -s 1024 -o file

   -e write=set
               Perform a full hexadecimal and ASCII dump of all the
               data written to file descriptors listed in the spec-
               ified  set.  For example, to see all output activity
               on file descriptors 3 and 5 use -e write=3,5.   Note
               that  this is independent from the normal tracing of
               the write(2) system call which is controlled by  the
               option -e trace=write.

Это распечатывает несколько больше, чем вам нужно (шестнадцатеричная часть), но вы можете легко отсеять это.

Я использовал strace и расшифровал шестнадцатеричный вывод для очистки текста:

PID=some_process_id
sudo strace -f -e trace=write -e verbose=none -e write=1,2 -q -p $PID -o "| grep '^ |' | cut -c11-60 | sed -e 's/ //g' | xxd -r -p"

Я собрал эту команду из других ответов.

strace выводит намного меньше, просто -ewrite (а не суффикс = 1). И это немного проще, чем метод GDB, IMO.

Я использовал его, чтобы увидеть прогресс существующего задания по кодированию MythTV (sudo, потому что у меня нет процесса кодирования):

$ ps -aef | grep -i handbrake
mythtv   25089 25085 99 16:01 ?        00:53:43 /usr/bin/HandBrakeCLI -i /var/lib/mythtv/recordings/1061_20111230122900.mpg -o /var/lib/mythtv/recordings/1061_20111230122900.mp4 -e x264 -b 1500 -E faac -B 256 -R 48 -w 720
jward    25293 20229  0 16:30 pts/1    00:00:00 grep --color=auto -i handbr

$ sudo strace -ewrite -p 25089
Process 25089 attached - interrupt to quit
write(1, "\rEncoding: task 1 of 1, 70.75 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.76 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.77 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.78 % "..., 73) = 73^C

Вы можете использовать reredirect (https://github.com/jerome-pouiller/reredirect/).

Тип

reredirect -m FILE PID

а выходные данные (стандартные и с ошибкой) будут записаны в ФАЙЛ.

перенаправлять README также объясняется, как восстановить исходное состояние процесса, как перенаправить на другую команду или перенаправить только stdout или stderr.

Вы не указали свою операционную систему, но я возьму удар и скажу «Linux».

Просмотр того, что пишется в stderr и stdout, вероятно, не поможет. Если это полезно, вы можете использовать tee (1) перед запуском сценария, чтобы взять копии stderr и stdout.

Вы можете использовать ps (1) для поиска wchan. Это говорит вам, чего ожидает процесс. Если вы посмотрите на вывод strace, вы можете проигнорировать большую часть вывода и определить последний (заблокированный) системный вызов. Если это операция над дескриптором файла, вы можете вернуться назад к выходным данным и определить базовый объект (файл, сокет, канал и т. Д.). Оттуда ответ, вероятно, будет ясен.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top