Как процесс может перехватывать stdout и stderr другого процесса в Linux?
Вопрос
У меня есть несколько скриптов, которые должны были перестать запускаться, но висят где-то вечно.
Есть ли какой-нибудь способ, которым я могу понять, что они пишут в 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').
Метод 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, вы можете проигнорировать большую часть вывода и определить последний (заблокированный) системный вызов. Если это операция над дескриптором файла, вы можете вернуться назад к выходным данным и определить базовый объект (файл, сокет, канал и т. Д.). Оттуда ответ, вероятно, будет ясен.
Вы также можете отправить процессу сигнал, который заставит его сбросить ядро, а затем использовать отладчик и файл ядра, чтобы получить трассировку стека.