[Visual Studio, Go, Разработка под Linux] Удаленная отладка Go-кода с VSCode без Remote Development

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
26-Авг-2020 15:31

В какой-то момент начинает требоваться отладить программу, которую нельзя отладить на рабочем компьютере. В моем случае потребовалось отладить программу, общающуюся по D-Bus с iwd, демоном, заведующим соединениями по Wi-Fi, на ноутбуке.
В VSCode есть аддон Remote Development, специально предназначенный для подобных случаев. Меня он не устраивал по нескольким причинам:
  • Автоматическое подписание коммитов GnuPG из VSCode не заработало.
  • Не заработал SSH-агент (вероятно, из-за отключенного проброса агента).
  • Не заработало, казалось бы, имеющееся в RD открытие локальной директории на удаленной машине (часть нужных файлов не была включена в версионный контроль, а ручным копированием по сети каждый раз заниматься не хотелось).

Я пишу на Go, так что хак, который я буду описывать, предназначен для отладчика Delve. Сам подход меняется мало вне зависимости от языка программирования; аналогичное можно сделать с используемым в VSCode для Python ptvsd и любым другим отладчиком, позволяющим удаленные соединения.

TL;DR поста

SPL
  • Пишем скрипт, собирающий бинарник с поддержкой отладки, копирующий ее на целевую машину по SCP и запускающий Delve.
  • Создаем в VSCode профиль отладки, аттачащийся к целевой машине.
  • Создаем в VSCode таск, запускающий скрипт из п.1 и добавляем его в зависимости профиля отладки.

Скриптуем сборку и запуск Delve
Delve умеет работать в режиме сервера отладки, позволяя подключаться по сети клиентам.
Для выполнения всей процедуры сборки/заливки/запуска dlv можно написать простой bash-скрипт или Makefile, но мне для их замены в таких случаях больше нравится Taskfile, поэтому приведу свой Taskfile.yml, который функционально мало чем отличается от shell-скрипта:
version: '2'
tasks:
  killall:
    cmds:
      # убиваем Delve на целевой машине,
      # завершаемся успешно вне зависимости от того,
      # был ли тот запущен
      - ssh target_machine killall dlv || true
  push:
    deps:
      - killall
    cmds:
      # собираем программу без оптимизаций
      - go build -gcflags="all=-N -l" -o ./build/debug_binary ./cmd/program
      # копируем бинарник на целевую машину
      - scp ./build/debug_binary target_machine:/home/tdemin/Desktop/debug_binary
  delve:
    deps:
      - push
    cmds:
      # запускаем dlv на целевой машине в режиме сервера на порту 64001;
      # хак с tmux здесь предназначен для того, чтобы убрать в фон
      # процесс dlv, оператор & или nohup с перенаправлением вывода
      # здесь недостаточны
      - ssh target_machine '(cd ~ && chmod +x Desktop/debug_binary && tmux new -d dlv --headless -l \[::\]:64001 exec ./Desktop/debug_binary)'

Весь процесс теперь можно запустить командой task delve; расставленные в Taskfile.yml зависимости обеспечивают завершение Delve (это необходимо делать перед SCP, потому что scp не позволит перезаписать в этот момент читаемый dlv бинарник), сборку/заливку и запуск нового процесса Delve в фоне на целевой машине.
Настройка профиля отладки
Файл .vscode/launch.json, определяющий профили отладки, здесь будет выглядеть следующим образом:
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Attach to target",
            // dlv использует API v1 по умолчанию,
            // это можно изменить ключом --api-version
            "apiVersion": 1,
            "type": "go",
            "request": "attach",
            "mode": "remote",
            // здесь это вроде бы не имеет значения; отладка, как
            // показывает опыт, работает нормально вне зависимости от того,
            // есть ли отлаживаемый исходник на целевой машине или нет
            "remotePath": "${workspaceFolder}",
            // зависимость от таска, таск будет запускаться каждый раз
            // перед запуском отладки
            "preLaunchTask": "Run Delve on target",
            "port": 64001,
            "host": "target_machine"
        }
    ]
}

Соответствующий таск сборки в файле .vscode/tasks.json будет выглядеть следующим образом:
{
    "version": "2.0.0",
    "tasks": [
        {
            // название таска должно совпадать с preLaunchTask в launch.json
            "label": "Run Delve on target",
            "type": "shell",
            // запускаем Taskfile
            "command": "task delve",
            "group": {
                "kind": "test",
                "isDefault": true
            },
            "presentation": {
                // не открываем терминал каждый раз при запуске
                // отладчика, это сильно раздражает
                "reveal": "silent"
            }
        }
    ]
}

Отладка
После того, как все настроено, можно нажимать F5, запустится сессия отладки:

Этот способ работает, но у него есть одно большое ограничение: встроенный в VSCode терминал не показывает стандартный ввод/вывод отлаживаемого процесса. Если они нужны, после запуска отладки можно по SSH прикрепиться к сессии tmux, в которой запущена в фоне программа.
Ссылки

===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_visual_studio, #_go, #_razrabotka_pod_linux (Разработка под Linux), #_golang, #_go, #_linux, #_vscode, #_visual_studio_code, #_razrabotka (разработка), #_otladka (отладка), #_delve, #_visual_studio, #_go, #_razrabotka_pod_linux (
Разработка под Linux
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 23-Ноя 00:06
Часовой пояс: UTC + 5