Один из возможных способов - использовать gdb
.
Прежде всего, вам нужны отладочные символы для вашего интерпретатора perl. Например, в моей системе Debian мне пришлось установить пакет perl-debug
. После установки у нас есть /usr/lib/debug/usr/bin/perl
, мы передадим это позже в gdb. Обратите внимание, что исходный, застрявший скрипт Perl был запущен с использованием /usr/bin/perl
, а не только с установленной версией отладки.
Ради этого примера, давайте запустим этот скрипт на Perl:
$ cat test.pl
#! /usr/bin/perl
use strict;
use warnings;
print "pid: ", $$, "\n";
while (1) {
print "line ", __LINE__, "\n"; sleep 1;
print "line ", __LINE__, "\n"; sleep 1;
}
Когда мы бежим, мы получаем выход, как:
$ ./test.pl
pid: 15764
line 9
line 10
line 9
line 10
^C
Теперь давайте запуска GDB. Используйте pid, напечатанный test.pl, прямо сейчас. Мы получаем подсказку после некоторой исходной информации ("Чтение символов из ..."):
$ gdb /usr/lib/debug/usr/bin/perl 15809
[snip]
(gdb)
В то же время, из-за присоединения GDB к интерпретатору Perl, Perl получает остановлен:
$ ./test.pl
pid: 15809
line 9
line 10
[snip]
line 9
line 10
line 9
[no further output]
Теперь давайте вернемся к БГД на трассировку:
(gdb) backtrace
#0 0x00007fd5b4479830 in __nanosleep_nocancel() at ../sysdeps/unix/syscall-template.S:82
#1 0x00007fd5b44796c0 in __sleep (seconds=<optimized out>) at ../sysdeps/unix/sysv/linux/sleep.c:138
#2 0x00007fd5b4efc1e2 in Perl_pp_sleep (my_perl=0x1a91010) at pp_sys.c:4586
#3 0x00007fd5b4ea89b6 in Perl_runops_standard (my_perl=0x1a91010) at run.c:41
#4 0x00007fd5b4e4a585 in S_run_body (oldscope=1, my_perl=0x1a91010) at perl.c:2350
#5 perl_run (my_perl=0x1a91010) at perl.c:2268
#6 0x0000000000400f89 in main (argc=2, argv=0x7fff4de87628, env=0x7fff4de87640) at perlmain.c:120
Как это было, вероятно, Perl случилось быть остановлен в середине сна(). Но какой?
Теперь нам нужно выяснить, где искать внутреннюю информацию perl в текущем исполняемом (Perl) исходном файле и строке. Первоначально я нашел некоторую релевантную информацию in the doumentation of mod_perl. Найдите макрос curinfo
.
(gdb) p my_perl->Icurcop->cop_file
$1 = 0x1abd810 "./test.pl"
(gdb) p my_perl->Icurcop->cop_line
$2 = 9
Как мы видим, мы находимся на линии 9 в test.pl - как и ожидалось на основе вывода сценария.
Связанная документация содержит несколько отличий в отношении бинарных файлов с перфорированными/не-потоковыми perl (пример выше для потокового perl, v5.14.2). Он также выглядит немного устаревшим, потому что он говорит о my_perl->Tcurcop
, в то время как я нашел то, что искал под именем my_perl->Icurcop
. На данный момент я недостаточно знаком с внутренними perl, чтобы понять, почему это переименовано.
Надеюсь, это поможет.
Возможный дубликат [Как подключить отладчик к запущенному процессу Perl?] (Http://stackoverflow.com/questions/8836711/how-can-i-attach-a-debugger-to-a-running -perl-process) – zoul
Спасибо за ответ. Мой запрос, возможно, более широкий по охвату. Я в порядке с решением, которое не требует, чтобы я прикреплял отладчик к процессу Perl. например если я могу ps ax + top сказать мне, что процесс не в узкой петле. – doon