2012-04-29 2 views
4

У меня очень тяжелое условие воспроизведения, когда процесс perl зависает. Я не уверен, где его повесили. ps ax | grep <process name> показывает столбец stat как SN, который, как я понимаю, означает, что он спит и работает с хорошим приоритетом.Как найти место, где висит скрипт perl (процесс linux)

Я просмотрел сценарий (там есть тон кода), но не может видеть какой-либо особый сон, который длится более нескольких секунд (этот процесс спал больше суток).

Я не могу перезапустить и добавить журнал в скрипты Perl, потому что условие не может быть воспроизведено. Я могу попробовать strace, но интересно, если есть лучший механизм

+0

Возможный дубликат [Как подключить отладчик к запущенному процессу Perl?] (Http://stackoverflow.com/questions/8836711/how-can-i-attach-a-debugger-to-a-running -perl-process) – zoul

+0

Спасибо за ответ. Мой запрос, возможно, более широкий по охвату. Я в порядке с решением, которое не требует, чтобы я прикреплял отладчик к процессу Perl. например если я могу ps ax + top сказать мне, что процесс не в узкой петле. – doon

ответ

4

Один из возможных способов - использовать 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, чтобы понять, почему это переименовано.

Надеюсь, это поможет.

1

Я знаю, что вы говорите, вы не можете перезапустить скрипт, но если вы сделать получить перезапустить его один раз, а не входить, попробуйте использовать Signal :: StackTrace или аналогичный так что в следующий раз, когда это произойдет, вы сможете поразить процесс с помощью USR2 и получить дамп трассировки стека.

Смежные вопросы