> Работал ли с systemd (Go)

Уровень: middle · Роль: backend · Категория: Технические вопросы

Компании: Wildberries

Стек: Go

> Пример ответа

Короткий ответ

Да, работал с systemd в рамках деплоя и эксплуатации Go-сервисов. Основной опыт - написание unit-файлов, настройка автозапуска, управление зависимостями между сервисами, работа с логами через journald, а также настройка environment-переменных и секретов. Использовал systemd как альтернативу Docker в простых продакшн-сценариях, где не нужна полная изоляция контейнера.

Подробное объяснение

systemd - это система инициализации и менеджер сервисов в современных Linux-дистрибутивах. Для Go-бэкенда ключевые возможности:

  • Unit-файлы - декларативное описание сервиса: команда запуска, рабочая директория, переменные окружения, рестарт-политика.
  • Зависимости - After, Requires, Wants для управления порядком запуска.
  • Журналирование - stdout/stderr процесса автоматически попадают в journald, что упрощает сбор логов.
  • Секреты и конфигурация - через EnvironmentFile или LoadCredential (в новых версиях).
  • Таймеры - замена cron для периодических задач.
  • Socket activation - возможность запускать сервис по запросу, хотя для Go это редко нужно.

Для Go-сервисов важно, что systemd корректно обрабатывает сигналы: при остановке сервиса отправляется SIGTERM, и Go-приложение должно gracefully завершиться, закрыв соединения и сохранив состояние.

На практике

Типичный сценарий для Go-микросервиса:

  1. Собираем бинарник статически (CGO_ENABLED=0), чтобы не зависеть от системных библиотек.
  2. Создаём unit-файл в /etc/systemd/system/myapp.service.
  3. Настраиваем Restart=on-failure с RestartSec=5 - это дешевле и надёжнее, чем самописный supervisor.
  4. Используем EnvironmentFile для конфигурации, чтобы не пересобирать бинарник при изменении настроек.
  5. Для graceful shutdown в Go-коде обрабатываем os.Interrupt и syscall.SIGTERM.

Также полезно: systemctl daemon-reload после изменения unit-файла, journalctl -u myapp -f для просмотра логов, systemctl status myapp для диагностики.

Пример кода

Пример unit-файла для Go-сервиса:

[Unit]
Description=My Go backend service
After=network.target postgresql.service
Wants=postgresql.service

[Service]
Type=simple
User=appuser
Group=appgroup
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp-server
Restart=on-failure
RestartSec=5
EnvironmentFile=/etc/myapp/env.conf
Environment=GIN_MODE=release
LimitNOFILE=65536

# Graceful shutdown
TimeoutStopSec=15
KillSignal=SIGTERM

[Install]
WantedBy=multi-user.target

Пример обработки сигналов в Go:

GO
func main() {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
srv := &http.Server{Addr: ":8080"}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal(err)
}
}()
<-ctx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
srv.Shutdown(shutdownCtx)
}

Как отвечать на собеседовании

  • Начни с конкретного примера: "Да, писал unit-файлы для Go-сервисов, настраивал рестарты и зависимости".
  • Упомяни, что понимаешь разницу между Type=simple и Type=notify (для Go обычно simple).
  • Покажи знание graceful shutdown - это важный момент для Go-разработчика.
  • Если есть опыт с Docker, отметь, когда systemd предпочтительнее (меньше оверхед, проще мониторинг системными инструментами).
  • Не углубляйся в экзотику (socket activation, cgroups), если не спрашивают.

Что проверяет интервьюер

  • Понимание жизненного цикла сервиса в Linux: запуск, остановка, рестарт, сигналы.
  • Умение конфигурировать окружение для приложения без Docker.
  • Знание механизмов логирования и мониторинга.
  • Понимание graceful shutdown и корректной обработки сигналов в Go.
  • Практический опыт деплоя, а не только теоретические знания.

Типичные ошибки

  • Говорить "systemd - это просто init", не упоминая управление сервисами.
  • Не знать про daemon-reload - частая ошибка при изменении unit-файлов.
  • Игнорировать обработку SIGTERM в Go-приложении - сервис "убивается" без закрытия соединений.
  • Путать Restart=always и Restart=on-failure - для сервисов с ошибками конфигурации always создаст бесконечный цикл рестартов.
  • Забывать про TimeoutStopSec - если приложение не завершится за это время, systemd отправит SIGKILL.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью