Есть скрипт на php, и он куда-то стучится. И вот появляется “плавающий баг”, когда скрипт иногда зависает и больше ничего не происходит. Нет ни нагрузки на процессор, ни на диск, но время выполнения уже “давно пройдено”.
Получаем PID
Для начала было бы хорошо глянуть “в процесс” скрипта, что бы увидеть что там происходит. Для этого через удобный
инструмент нужно получить PID
. На примере ps
:
|
|
Первый столбец это и есть нужный нам PID
: 144275
.
Alpine linux
Так получается, что для Alpine linux ps
это всего лишь ссылка на busybox
:
|
|
Установить полноценный ps
можно так:
|
|
Если нет возможности установить его, то модифицируем команду с поиском (а точнее упростим по сравнению с ps
):
|
|
Как видим PID
тут точно такой же как и при использовании полноценного ps
-а: 144275
.
Процесс выполнения скрипта
Что бы понять действительно ли он завис, или просто выполняет долгую операцию достаточно выполнить strace
по
полученному ранее PID
-у:
|
|
Судя по зацикленному выводу poll, rt_sigaction, poll, rt_sigaction, rt_sigaction, poll, ...
скрипт повис. Повис он на
попытке выполнить poll каких-то данных. В вызове мы видим и
идентификатор файлового дескриптора (fd
), из которого и происходит попытка получения данных.
Ищем файловый дескриптор
Теперь у нас есть PID
(144275
) и номер файлового дескриптора (11
). Узнать что же за ним скрывается можно
через lsof
с помощью такой команды:
|
|
Тут мы видим, что это TCP соединение со сторонним сервером. По ip адресу можно более менее понять куда происходит соединение и копать в эту сторону.
Alpine linux
Как и с ps
, lsof
тут по умолчанию ведет на busybox
:
|
|
Установить полноценный lsof
можно так:
|
|
Если по какой-то причине установить не представляется возможным, то придется немного “модифицировать” запрос lsof
. Сам
он не отфильтрует результат (да и значения будут “сырыми”):
|
|
Тут номер дескриптора идет в третьем столбце. Значит нас интересует socket:[718693431]
, в обычном выводе это
столбец DEVICE
. Тут же придется поискать устройство “руками”. Ищем в /proc/net/tcp
(благо мы уже знаем, что это tcp
соединение):
|
|
Интересный момент, но адреса и порты тут записаны в шестнадцатеричном формате. Сам ip адрес отображен задом-на-перед. То есть декодируем:
Адреса tcp соединения | local_address | rem_address |
---|---|---|
Начальное значение | 0453E30A:83F4 | 7182FC54:01BB |
Добавляем точки | 04.53.E3.0A:83F4 | 71.82.FC.54:01BB |
Переводим в десятичную систему счисления | 4.83.227.10:33780 | 113.130.252.84:443 |
Отображаем ip адрес | 10.227.83.4:33780 | 84.252.130.113:443 |
Получается, повисшее соединение: 10.227.83.4:33780->84.252.130.113:443
, что соответствует выводу полноценного lsof
.