Процесс, запущенный с помощью nohup, завершается с ошибкой client_loop: send disconnect: Broken pipe.

Вопрос или проблема

Я наблюдал следующее и хочу понять, почему:

Во-первых, я запускаю Node сервер, который прослушивает порт на удаленном сервере, используя:

nohup my-app &

Далее есть два случая:

  1. Я выхожу из удаленного сервера, используя exit. Я называю это корректным выходом
  2. Я не выхожу корректно, но вместо этого происходит принудительный выход, поскольку мой локальный компьютер переходит в спящий режим после длительного периода бездействия или что-то в этом роде. В этом случае я вижу сообщение на экране: client_loop: send disconnect: Broken pipe

Когда я снова вхожу в систему, в случае 1 процесс все еще работает, но в случае 2 он завершен. Почему?

И чтобы добавить поворот, случай 1 и случай 2 ведут себя одинаково на Mac, но не в Windows (используя WSL2). Мне очень любопытно понять, что здесь происходит и почему Windows (WSL2) и Mac ведут себя по-разному.

Ответ или решение

Теория

Когда вы запускаете процесс с помощью nohup, ожидается, что он будет продолжать своё выполнение в фоновом режиме, даже если пользователь завершает сеанс, закрывает терминал или выходит из системы. nohup (от "no hang up") игнорирует сигнал HUP (SIGHUP), который обычно посылается при завершении сеанса, чтобы гарантировать, что процесс не будет неожиданно прерван. Запуск процесса командой nohup my-app & помещает процесс в фоновый режим и перенаправляет его стандартный вывод в файл nohup.out для предотвращения потери данных, которые могут быть выведены во время его выполнения.

Когда вы выполняете "грациозный" выход из системы, отправляя команду exit, SSH клиент завершает соединение корректно. Это позволяет nohup продолжать выполнение процесса, поскольку все сигналы обрабатываются контролируемым образом.

Однако проблема возникает в случае неблагоприятного завершения соединения, например, когда ваш компьютер неожиданно переходит в режим сна. В этом случае SSH-сессия прерывается без предварительного уведомления. В результате может возникнуть сообщение об ошибке client_loop: send disconnect: Broken pipe, что указывает на то, что SSH-клиент потерял соединение с сервером, впервые заметив неожиданное закрытие канала передачи данных.

Пример

Возьмем сценарий с использованием SSH на удалённом сервере, где выполняется серверное приложение Node.js, как описано выше. В первом случае, по завершении сеанса с помощью команды exit, ваш сеанс SSH завершает соединение должным образом, отправляя соответствующие сигналы и уведомления всем подпроцессам (в том числе и тем, которые управляются nohup). Так как nohup игнорирует сигналы, которые обычно ведут к завершению процесса при закрытии сессии, процесс продолжает выполняться на сервере.

Во втором случае, если ваша система переходит в ждущий режим или теряет сетевое соединение, SSH-сессия прерывается без возможности заранее отправить уведомления процессам о закрытии сессии. Вследствие этого, если участие TTY важно для приложения или оно связано с системами, требующими активного соединения, процесс может быть завершен. Для WSL 2 на Windows, управление процессами может отличаться благодаря добавочному слою абстракции виртуализации, что может привести к прекращению процесса при неожиданных изменениях состояния подключения.

Применение

Для достижения большей надежности работы приложения в обоих упомянутых случаях можно рассмотреть несколько вариантов решения:

  1. Использование экранных сессий или tmux: Screen или tmux создают самостоятельные сессии, которые можно отделить от TTY. Это означает, что вы можете начать процесс в этой сессии, а затем отсоединиться от неё, оставив процесс работающим, независимо от состояния SSH-сессии.

    screen -S mysession
    my-app
    (Ctrl+a, d)  # Отсоединение от сессии без завершения процессов
  2. Рассмотрение использования Systemd: Если у вас есть возможность настройки Systemd на вашем сервере, это может быть хорошим решением для управления фоновыми службами. Оно обеспечивает автоматический перезапуск, управление зависимостями и управление запуском и остановкой каждого процесса в более сложных системах.

  3. Проверка и настройка KeepAlive для SSH: Убедитесь, что конфигурация SSH отвечает за поддержание активного соединения. Параметры, такие как ClientAliveInterval и ClientAliveCountMax, могут быть настроены для продления активности соединения при временных потерях соединения.

Разные поведения на платформах

Что касается различий между Mac и Windows (WSL 2), это связано с различиями в системных ядрах и управлении процессами. WSL 2 использует виртуализированное ядро Linux, работающее поверх Windows, что иногда приводит к различиям в поведении по сравнению с системами macOS, которая взаимодействует с ядром Unix напрямую.

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

Оцените материал
Добавить комментарий

Капча загружается...