Можно ли запустить приложение WSL в фоновом режиме?

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

Я установил LXD в Ubuntu через Snap Store и затем подключил его к клиенту Windows, но для того, чтобы запускать контейнеры из Windows, приложение Ubuntu должно быть открыто. Есть ли способ запустить сервер LXD в фоновом режиме или мне придется держать Ubuntu открытой, чтобы это работало?

wsl --status возвращает:

Default Distribution: Ubuntu
Default Version: 2

wsl --version возвращает:

WSL version: 0.70.0.0
Kernel version: 5.15.68.1
WSLg version: 1.0.45
MSRDC version: 1.2.3575
Direct3D version: 1.606.4
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22000.1098

и cmd /c ver возвращает:

Microsoft Windows [Version 10.0.22000.1098]

Это, честно говоря, замечательный вопрос, поскольку я осознал это, пройдя через различные сценарии ниже. В том, как работает WSL, я вынужден согласиться, есть некая путаница. Существует ряд “проблем”, связанных с этим, на репозитории WSL на GitHub, но реальность такова, что это поведение “преднамеренно”.

Из анонса WSL/Systemd:

Также важно отметить, что с этими изменениями службы systemd НЕ будут поддерживать вашу WSL-инстанцию в активном состоянии. Ваша WSL-инстанция будет оставаться активной так же, как и раньше, о чем вы можете [узнать подробнее здесь](https://devblogs.microsoft.com/commandline/background-task-support-in-wsl/).

Другими словами, WSL разработан так, чтобы завершать Ubuntu в определенных ситуациях, но связанное сообщение не совсем ясно, что это за сценарии. Чтобы лучше понять их (и как ведет себя WSL), давайте начнем с (по крайней мере) четырех различных способов, как вы можете запустить фоновую задачу или службу (также известную как демон) в Ubuntu на WSL:

  1. Интерактивно, из командной строки через саму команду или с помощью вспомогательной программы service. Например:

    sudo service cron start
    # или даже
    sudo /usr/sbin/cron
    

    Это, конечно, будет работать на любой версии WSL, но SysVInit service может работать только для определенных дистрибутивов (таких как Ubuntu) и служб.

    (Важно) обратите внимание, что команды, выполняемые внутри сценариев запуска вашего шелла, считаются “интерактивными” для этой цели. Это пригодится в моем окончательном (не очень аккуратном) решении.

  2. Интерактивно, как фоновая задача из шелла. Например:

    nohup sleep 100000 &
    
  3. В Windows 11 вы можете автоматически запустить демон при запуске WSL через /etc/wsl.conf. Например:

    [boot]
    command = service cron start
    
  4. И начиная с WSL 0.67.6, используя Systemd. Это может происходить либо интерактивно (sudo systemctl cron start), автоматически через ссылки /etc/systemd, либо как зависимость другой службы. Например:

    sudo systemctl cron start
    

    Обратите внимание, что демон Snap (snapd) запускается автоматически через Systemd, как только он включен в WSL.


С учетом этих сценариев, мы должны рассмотреть когда WSL завершит Ubuntu. Как я уже говорил, это “путаница”. Мне бы хотелось сформулировать резюме, чтобы описать поведение, но мне это дается с трудом. Лучшее, что я могу сделать, это привести примеры:

Резюме

  1. Не завершит
  2. Не завершит
  3. Завершит
  4. Завершит

Детали и примеры

  1. Служба, запущенная интерактивно через командную строку, предотвратит завершение Ubuntu WSL. Мы можем продемонстрировать это следующим образом:

    • Временно отключив Systemd в /etc/wsl.conf
    • Выйдя из Ubuntu
    • Запустив PowerShell
    • wsl --shutdown
    • Перезапустив Ubuntu через wsl ~ (если нужно, wsl ~ -d Ubuntu-22.04 и т. д.)
    • sudo service cron start
    • Выйдя из шелла
    • Подождав минуту (25 секунд по умолчанию, этого должно быть достаточно) и проверив wsl -l -v, чтобы показать, что Ubuntu все еще находится в состоянии Работающие.
    • wsl -e ps axjff должно показать, что cron все еще работает, даже если ни один шелл не работает.
  2. Фоновая задача, запущенная интерактивно через командную строку, также предотвратит завершение Ubuntu WSL. Следуя предыдущему примеру:

    • При отключенном Systemd, из PowerShell, wsl --shutdown
    • Запустите Ubuntu (например, wsl ~)
    • Выполните nohup sleep 100000 &
    • Нажмите Enter один раз дополнительно, чтобы закрыть сообщение nohup
    • Выйдите из шелла/Ubuntu обратно в PowerShell.
    • Подождите 30 секунд до минуты и выполните wsl -l -v, чтобы показать, что Ubuntu все еще работает.
    • wsl -e ps axjff должно показать, что команда sleep все еще работает, даже если ни один шелл не работает.
  3. Служба/процесс, запущенный через /etc/wsl.conf, с другой стороны, не предотвратит завершение Ubuntu WSL.

    • Начинаем с предыдущего примера (Systemd отключен)

    • В Ubuntu выполните sudo -e /etc/wsl.conf и добавьте следующее:

      [boot]
      command = service cron start
      
    • Выйдите из Ubuntu и из PowerShell выполните wsl --shutdown

    • Перезапустите Ubuntu через wsl ~

    • ps axjff покажет, что cron работает как подсистема одного из /init родительских процессов.

    • Выйдите из шелла/Ubuntu

    • Через 30 секунд до минуты wsl -l -v покажет, что Ubuntu больше не работает. Она была завершена.

  4. Служба/процесс, запущенный через Systemd, также не позволит WSL завершить Ubuntu. Демонстрация (хотя вы уже это переживаете):

    • Отредактируйте /etc/wsl.conf и повторно включите Systemd, отключив (закомментировав или удалив) command.

    • Выйдите из Ubuntu

    • В PowerShell выполните wsl --shutdown

    • wsl ~ для запуска Ubuntu.

    • ps axjff покажет, что службы Systemd запущены и/или запускаются.

    • Через минуту:

      sudo systemctl stop cron
      sudo systemctl start cron
      

      Это, очевидно, имеет эффект простого остановки cron, а затем его перезапуска. Суть в том, чтобы показать, что даже если мы явно запустили cron интерактивно, это не предотвратит завершение Ubuntu WSL.

    • Выйдите из шелла/Ubuntu

    • Через 30 секунд до минуты wsl -l -v покажет, что Ubuntu была Остановлена.

    Что касается вашего конкретного вопроса, поскольку lxd – это просто Snap, который работает в контейнеризированной среде, запущенной Systemd, он также завершается. Вот так, к сожалению …

Решение

Надеюсь, вскоре будет более постоянное решение, так как один из разработчиков WSL действительно выразил желание поддерживать работающие дистрибутивы.

Тем временем решение (и, конечно, может быть больше) заключается в том, чтобы запустить длительный процесс через ваши файлы запуска оболочки. В моем случае я обычно использую keychain.

Есть несколько особенностей Keychain, которые позволяют ему хорошо работать в этом случае:

  • Он доступен в стандартных репозиториях Ubuntu
  • Он уже запускает единичный экземпляр ssh-agent. Другими словами, если ssh-agent уже работает, он прикрепляется к нему, а не запускает новый.
  • Он может работать тихо и без взаимодействия, если ключи не добавляются

Чтобы настроить это:

sudo apt update && sudo apt install keychain -y
sudo -e /etc/profile.d/keep_wsl_running.sh

И добавьте следующее:

#!/usr/bin/env sh
eval $(keychain -q)

Этот скрипт:

  • Запускается, когда вы запускаете свою оболочку (предполагая, что это большинство оболочек, таких как Bash и Zsh). Обратите внимание, что он не сработает, если вы используете Fish в качестве своей оболочки. Если вы (или любой будущий читатель) хотите использовать Fish (или другую оболочку, которая не обрабатывает /etc/profile.d), задайте отдельный вопрос о том, как обработать этот сценарий. У меня есть решение, но этот ответ (как обычно) уже достаточно длинный ;-).

  • Оценивает вывод keychain, чтобы найти любой существующий ssh-agent (или запустить новый, если не найден) и установить переменные окружения для оболочки, чтобы они указывали на него.

  • -q, как вы, вероятно, уже догадались, просто запускает keychain тихо, без вывода

Наличие работающего ssh-agent (который был запущен через /etc/profile.d) предотвратит завершение дистрибутива/инстанции/контейнера Ubuntu WSL. Ubuntu будет продолжать работать после закрытия окна терминала, и ваш lxd (и другие демоны/службы, установленные Snap) также останутся активными.

Чтобы позволить Ubuntu завершиться корректно, просто избавьтесь от ssh-agent. Это можно сделать несколькими способами, в том числе:

keychain -k all

Конечно, убедитесь, что все другие службы, которые вы запускали интерактивно, также отсутствуют. Как только это условие будет выполнено, WSL корректно завершит Systemd и его юниты/службы.

Есть один крайний случай, и это когда вы начнете сессию wsl -u root. В этом случае ssh-agent также будет запущен от имени root, и вам нужно будет выполнить sudo keychain -k all.

Запустите этот vbs-скрипт при запуске Windows. Просто положите его в папку автозагрузки Windows (crl+r -> shell:startup)

wsl-startup.vbs:

# измените '<Distro>' на название используемого вами дистрибутива.
set ws=wscript.CreateObject("wscript.shell")
ws.run "wsl -d <Distro>", 0

источник: https://github.com/microsoft/WSL/issues/8854#issuecomment-1421910739

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

Затем вы можете использовать systemd, чтобы запускать что угодно в фоновом режиме.

Не забудьте снова запустить vbs, если вы вручную перезапустите экземпляр wsl с помощью wsl -t <distro> / wsl --shutdown


обновление 2024/10/25:

Или вы можете просто добавить это в ~/.bashrc

if ! ps a | grep '[s]leep 1h' > /dev/null; then
    nohup sleep 1h > /dev/null 2>&1 &
fi

Измените время сна по вашему желанию. Когда есть процесс сна, WSL будет продолжать работать.

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

Вопрос: Возможно ли запускать приложение WSL в фоновом режиме?

С учетом того, что вы установили LXD на Ubuntu и подключили его к клиенту Windows, становится очевидным, что вопрос о том, может ли сервер LXD работать в фоновом режиме без активного окна Ubuntu, – это важный аспект для обеспечения непрерывной работы контейнеров. Ваша текущая версия WSL и другие конфигурации значительно влияют на это.

Основы работы WSL

WSL (Windows Subsystem for Linux) обеспечивает совместимость операций Linux непосредственно в Windows, но его поведение в контексте фоновых процессов и служб требует понимания. Согласно последним изменениям в WSL, включая поддержку systemd, становится понятно, что службы, запущенные в WSL, не будут поддерживать активное состояние дистрибутива, если окно терминала будет закрыто.

Как работают фоновые процессы в WSL

В WSL есть несколько способов запуска фоновых задач, но ключевым аспектом является то, что не все из них сохраняют состояние дистрибутива. Рассмотрим некоторые способы:

  1. Интерактивный запуск из командной строки:
    Команда, запущенная в терминале, будет удерживать WSL активной, пока эта команда выполняется.

    sudo service cron start
  2. Запуск фонового процесса:
    Можно использовать nohup для запуска задачи в фоновом режиме, и это также будет удерживать WSL активной:

    nohup sleep 100000 &
  3. Автоматический запуск служб через wsl.conf:
    Настройка в wsl.conf может не удерживать состояние WSL активным, поскольку такие команды исполняются лишь при инициализации дистрибутива и не препятствуют его завершению.

    [boot]
    command = service cron start
  4. Использование systemd:
    Службы, запущенные через systemd, также не предотвращают завершение работы WSL после закрытия терминала.

Поведение WSL при завершении

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

  • Если была выполнена интерактивная команда или фоновая задача из терминала, то WSL останется активным.
  • Если службы были запущены через wsl.conf или systemd, WSL может быть завершен после закрытия терминала.

Решение проблемы: как запустить WSL в фоновом режиме

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

  1. Применение Systemd:
    Вы можете активировать systemd в вашем дистрибутиве. Это позволит управлять службами более эффективно.

  2. Использование VBS-скрипта:
    Написание VBS-скрипта для автоматического запуска WSL при старте Windows:

    set ws=wscript.CreateObject("wscript.shell")
    ws.run "wsl -d Ubuntu", 0

    Сохраните скрипт в папке автозагрузки Windows, чтобы запускать WSL при каждом входе в систему.

  3. ~/.bashrc для удержания WSL:
    Добавьте проверку и команду в ~/.bashrc, чтобы запускать sleep, это будет удерживать экземпляр WSL активным.

    if ! ps a | grep '[s]leep 1h' > /dev/null; then
       nohup sleep 1h > /dev/null 2>&1 &
    fi

Заключение

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

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

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