Ответ 1
Я не уверен, что это сработает для вас, но я прочитал страницу некоторое время назад, описывая метод
У меня есть некоторые скрипты, которые должны были перестать работать, но повесить навсегда.
Можно ли каким-то образом понять, что они пишут для stdout и stderr в читаемом виде?
Я попытался, например, сделать
tail -f /proc/(pid)/fd/1
но это не работает. В любом случае это был длинный выстрел.
Любые другие идеи? strace сама по себе довольно многословна и нечитаема для наблюдения за этим.
Примечание. Меня интересует только их выход, а не что-то еще. Я могу разобраться в других вещах самостоятельно; этот вопрос ориентирован только на получение доступа к stdout и stderr запущенного процесса после его запуска.
Я не уверен, что это сработает для вас, но я прочитал страницу некоторое время назад, описывая метод
Так как мне не разрешено редактировать ответ Jauco, я дам полный ответ, который сработал у меня (страница Рассела полагается на необоснованное поведение, которое, если вы закроете fd 1 для stdout, следующий вызов creat откроет fd 1.
Итак, запустите простой бесконечный script следующим образом:
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
Теперь вы можете tail/tmp/stdout и видеть вывод, который использовался для перехода на стандартный вывод.
Есть несколько новых утилит, которые завершают "метод gdb" и добавляют дополнительные штрихи. Тот, который я использую сейчас, называется "reptyr" ( "Re-PTY-er" ). Помимо захвата STDERR/STDOUT, он фактически изменит управляющий терминал процесса (даже если он ранее не был присоединен к терминалу).
Лучше всего использовать сеанс экрана и использовать его для повторного подключения выполняемого процесса к терминалу на экране, чтобы вы могли безопасно отсоединиться от него и вернуться позже.
Он упакован на популярные дистрибутивы (Ex: 'apt-get install reptyr').
Метод Gdb кажется лучше, но вы также можете сделать это с помощью strace:
strace -p -e write = 1 -s 1024 -o файл
-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
и выходы (стандарт и ошибка) будут записаны в FILE.
reredirect README
также объясняет, как восстановить исходное состояние процесса, как перенаправить на другую команду или перенаправить только stdout или stderr.
Вы не указываете свою операционную систему, но я собираюсь взять удар и сказать "Linux".
Увидеть, что написано в stderr и stdout, вероятно, не поможет. Если это полезно, вы можете использовать tee (1), прежде чем запускать script, чтобы взять копию stderr и stdout.
Вы можете использовать ps (1) для поиска wchan. Это говорит о том, что ждет процесс. Если вы посмотрите на вывод strace, вы можете игнорировать основную часть вывода и идентифицировать последний (заблокированный) системный вызов. Если это операция с дескриптором файла, вы можете вернуться в обратном направлении и идентифицировать базовый объект (файл, сокет, канал и т.д.). Оттуда ответ будет явно понятным.
Вы также можете отправить процессу сигнал, который заставляет его выгружать ядро, а затем использовать отладчик и основной файл для получения трассировки стека.