Как отладить программу, к которой у тебя нет доступа

Автор оригинала: keypressingmonkey
  • Перевод

Фото: Intricate Explorer, Unsplash

Сегодня я вспомнил один из любимых «программистских мифов», который вполне может быть городской легендой, и свою собственную версию «чёрного ящика», который требовал отладки.

Городская легенда повествует о радиоактивных железнодорожных вагонах из Украины, вызывавших баги в компьютерной системе, прочитать её можно здесь.

Разбираемся с «чёрными ящиками» и c тем, какими они бывают сегодня


«Чёрный ящик» — это популярная концепция программирования, предполагающая, что мы находимся снаружи системы или компонента, не имея прямого доступа к коду. Это может быть вызвано различными факторами:

  • Вы работаете со сторонним ПО, разработчики которого просто не раскрывают код.
  • Вы взаимодействуете с API, внутренняя логика которого абстрагирована.
  • У вас нет необходимых полномочий для доступа к Git-репозиторию.
  • Даже система с полным доступом может де-факто стать «чёрным ящиком» из-за своей сложности.
  • Сотрудник, обладавший всеми ключами и знаниями, внезапно уволился/пропал/умер.
  • Легаси-система состоит из .dll, которая «всегда работала» на сервере, и не была подключена к системе контроля версий. Чтобы просто посмотреть на код, её нужно декомпилировать, если это возможно, конечно.

Все эти факторы сводятся к тому, что у нас есть проблема, которую мы не можем устранить мгновенно, и мы не знаем, в чём заключается ошибка. Поэтому нам нужно браться за работу.

Наша собственная проблема была сочетанием всего вышеперечисленного


Список перечисленных выше факторов, вероятно, не описывает все ситуации, потому что это непосредственный список факторов, повлиявших на нашу ситуацию. У нас был только что уволен разработчик, сложная система, распределённая по нескольким серверам, с основной .dll, которая «делала своё дело», хотя никто и не знал, почему и какое именно.

Она вызывала сторонние сервисы, в ней практически отсутствовал логгинг, и единственными резервными копиями, которые у нас имелись, были хранилища в файловой системе с этой .dll
и без какого-либо кода. Как можно понять, ничто из этого невозможно было поддерживать, и систему планировали в своё время переписать, но ошибка была экстренной и требовала устранения.

Можно сказать, что бОльшую часть времени система почти полностью справлялась с работой, и мы могли бы мириться с частичными решениями проблемы, если бы они демонстрировали постоянство. Однако примерно каждое сотое множество данных оказывалось с неверными результатами и единственное, что мы могли делать — отлаживать их снаружи (сейчас мы вспоминаем об этом с улыбкой).

Это один из тех случаев, когда я испытал благодарность за хаотический мир, в котором вырос, потому что большинство компаний не столкнётся с настолько серьёзными проблемами, и не назначит решать их недавнего выпускника. Мне в этом смысле повезло, и ещё больше повезло, потому что у меня была поддержка опытных разработчиков, помогавших мне на протяжении всего процесса. Итак, вот каким было наше решение.

Воспроизводим ошибку (в идеале на нескольких тестовых случаях)


Когда вы узнаете, в чём заключается настоящая ошибка, проблема будет почти решена, но дойти до этого может быть невероятно сложно, если ошибка проявляется нерегулярно. Вспомним снова о примере с поездами — если бы не удалось выявить паттерн, то причину найти было бы почти невозможно. Потому что именно это мы ищем в такой ситуации — паттерн того, когда происходит ошибка.

В нашем случае мы обнаружили его относительно просто: мы знали тип ошибки и она возникала многократно, однако так редко, что нам понадобилось много времен, чтобы сузить пространство поиска случаев и выявить их логику.

После того, как мы выявили множество тестовых случаев, регулярно приводящих к сбоям, можно приступать к самой отладке. Вот пример другого процесса, в котором мы сузили поиски источника проблемы сопоставлением паттернов: одна из систем зависала каждую ночь четверга, при этом в файлах логов не было ничего странного:

  • Мы знали, что наша система не выдавала никаких сообщений об ошибке, однако зависала.
  • Мы сопоставляли случаи, пока не удостоверились, что проблема возникает в четверг и больше ни в какие другие дни.
  • Мы проверили, что на это время не запланировано никаких автоматических обновлений, проверили все автоматизированные задачи, работающие на том же сервере — ничего.
  • Мы посмотрели, что делает система на метауровне, и сузили проблему до таймаута общего диска, к которому каждые две недели получала доступ задача очистки диска, запущенная на совершенно другом сервере во время работы нашего сервиса. Никто не подумал о том, что обе они начинались запускаться в три часа ночи.

Создаём тестовое окружение (даже если это продакшен)


Получив набор ошибок, можно приступать к работе над истинной причиной и решением, а для этого нужна тестовая система.

Под этим я подразумеваю, что вам требуются две константы:

  • Используемые данные не должны изменяться другими системами
  • Возможный урон должен быть максимально ограничен

В нашем случае мы не могли воспроизвести ошибки на тестовом сервере, это было очевидно, поскольку по сравнению с сервером в продакшене библиотека .dll находилась в совершенно ином состоянии. Откат к этому старому состоянию не сработал, потому что ломал другие элементы, которые были столь же важны.

Поэтому мы собрались и задались вопросом: «что самое худшее может произойти, если мы это испортим?», а потом написали скрипт базы данных, переписывающий все результаты в ошибочное состояние, чтобы последующие системы не обрабатывали их.

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

Сравниваем входящие данные, чтобы найти сходства и различия с работающими множествами данных


Хоть мы и не можем узнать, что же конкретно делает код в случае «чёрного ящика», можно было провести своеобразный «реверс-инжиниринг», часто дающий хорошее понимание причин проблем.

В нашем случае мы обладали роскошью в виде достаточно качественно отформатированных файлов JSON от предыдущей системы, от которых зависели наши входящие данные. После того, как мы всё подготовили, оставалось в буквальном смысле начать сравнивать пару текстовых файлов в Notepad++, пока не найдём сходства между файлами, вызывающими ошибки, а затем различия между ними и правильно работающими файлами.

Тут нам повезло — мы быстро смогли выяснить, что баг вызывает конкретное сочетание флагов заказчика, и нам сразу же удалось их обойти, потому что этот случай можно было «имитировать» похожими, но другими флагами. Поэтому поскольку мы уже знали, что систему будут переписывать (на самом деле, у нас и не было выбора), было решено обойти этот баг вместо декомпиляции и его устранения.

Изменяем входящие данные, чтобы убедиться, что наша догадка привела к ожидаемым результатам (и ограничивает любой урон)


Очевидно, что менять «живые» данные в базе данных в продакшене, надеясь, что всё будет работать без реального тестирования — плохая идея, но у нас не было другого выбора.

Всё сработало отлично, ведь количество случаев было низким, а первые несколько тестов мы провели ручную и оказалось, что они в точности создают требуемые результаты.

Поэтому в конечном итоге мы просто написали ещё одну автоматизированную задачу, устранявшую эти проблемы до того, как они попадут в систему, а затем приступили к трёхмесячному проекту по переписыванию этой программы с нуля, на этот раз прозрачно, с системой контроля версий и конвейерами сборки.

Вот такое приключение.

Вывод: о системе можно узнать довольно много, даже если просто походить вокруг неё и потыкать в неё палочкой


Меня этот способ отладки и поиска ошибок восхищает, я люблю, когда программирование сочетается с всплеском адреналина.

Если вы не смотрели видео об SQL-инъекции и реверс-инжиниринге базы данных по сообщениям об ошибках, крайне рекомендую его посмотреть. Использованные в этом видео методики почти идентичны с теми, которые можно применять для незлонамеренной отладки.



На правах рекламы


Закажите и сразу работайте! Создание VDS любой конфигурации в течение минуты, в том числе серверов для хранения большого объёма данных до 4000 ГБ. Эпичненько :)

Подписывайтесь на наш чат в Telegram.

VDSina.ru
Серверы в Москве и Амстердаме

Комментарии 3

    +7

    Я так и не понял, о чем это. Думал будет про методики отладки, внедрение в процесс, перехват событий, ещё что-то. А тут нашли json который ломает приклад и написали фильтр, который изменяет этот json. Зато заголовок...

      +5
      Отладка в 2000-м — SoftICE, отладка сейчас — как в статье
      +1

      Я думал это будет про удалённую отладку приложения, когда надо сделать отладку на сервере а не локально, а тут тыкание палкой в не пойми что и не пойми как

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое