Удивительно, но после 5 лет или около того WSL, похоже, не было хорошего вопроса общего назначения «Systemd» здесь, в Ask Ubuntu. Так что это выглядит как хороший, чтобы использовать для этой цели.
Эта проблема
В общем, когда вы видите либо из следующих двух сообщений:
Система не была загружена с systemd в качестве системы инициализации (PID 1). Не могу работать.
Не удалось подключиться к шине: хост не работает
Тогда это, как правило, одна и та же основная причина. В случае systemctl
и попытка начать ssh
, вы видите оба.
Основная проблема, как упоминалось в комментариях, заключается в том, что WSL не использует Systemd, даже в дистрибутивах, где он используется по умолчанию. Вместо этого WSL в настоящее время использует собственный /в этом
процесс как PID 1, который выполняет несколько специфичных для WSL задач, о которых я упоминал в этот ответ (поэтому я не буду повторять их здесь).
И хотя WSL — это (ИМХО) отличный способ иметь полнофункциональный Linux CLI в Windows (а в последнее время — даже графический интерфейс), отсутствие Systemd, как правило, усложняет задачу в дистрибутивах, которые ожидать быть там. К счастью, Ubuntu в целом неплохо справляется с задачей без Systemd.
Как справиться с отсутствием Systemd
И несмотря на это, Systemd по своей сути является просто (вероятно, грубым упрощением) «способом выполнения системных задач». Существует (обычно? всегда?) способ выполнения одной и той же задачи без Systemd, а часто и более одного способа.
Вариант 1: «По старинке»
В Ubuntu на WSL многие из общих системных служб все еще имеют «старый» init.d
сценарии, которые можно использовать вместо systemctl
с модулями Systemd. Вы можете увидеть их, используя лс /etc/init.d/
.
Так, например, вы можете начать ssh
с запуск службы sudo по ssh
, и он будет запускать /etc/init.d/ssh
сценарий с Начало
аргумент.
Даже некоторые пакеты не по умолчанию, такие как MySql/MariaDB, будут устанавливать оба файла модулей Systemd. и Старый init.d
скрипты, так что вы по-прежнему можете использовать оказание услуг
команда для них, а также.
Вариант 2: «Ручной» способ
Но у некоторых служб нет эквивалента сценария инициализации, особенно в других дистрибутивах. Для простоты предположим, что ssh
init.d
сценарий не было имеется в наличии.
В этом случае «ответ» состоит в том, чтобы выяснить, что делают файлы модулей Systemd, и попытаться воспроизвести это вручную. Это может сильно различаться по сложности. Но я бы начал с просмотра файла модуля Systemd, который вы пытаетесь запустить:
меньше /lib/systemd/system/ssh.service
# Обрезано
[Оказание услуг]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
RuntimeDirectory=sshd
RuntimeDirectoryMode = 0755
Я вырезал некоторые менее важные строки для понимания его поведения, но вы можете человек systemd.exec
, человек systemd.service
и другие, чтобы увидеть, что делает большинство параметров.
В этом случае, когда вы sudo systemctl запустить ssh
, Это:
- Читает переменные окружения (т.
$SSHD_OPTS
) от /etc/по умолчанию/ssh
- Проверяет конфигурацию, завершает работу в случае сбоя
- Проверяет существование RuntimeDirectory с указанными разрешениями. Это переводится как
/выполнить/sshd
(от человек systemd.exec
). Это также удаляет каталог среды выполнения при остановке службы.
- работает
/usr/sbin/sshd
с опциями
Итак, если у вас нет конфигурации на основе среды, вы можете просто настроить скрипт для:
- Убедитесь, что каталог среды выполнения существует. Обратите внимание, что, поскольку он находится в
/бег
, который является tmpfs
mount, он будет удаляться после каждого перезапуска экземпляра WSL.
- Установите разрешения на
0755
- Начинать
/usr/sbin/sshd
как корень
... И вы бы сделали то же самое вручную без системд.
Опять же, это, вероятно, самый простой пример. У вас может быть гораздо больше работы для более сложных задач.
Вариант 3. Запустите Systemd как PID 1 в пространстве имен/контейнере PID.
Наконец, это возможное чтобы запустить Systemd под WSL. Это довольно сложная тема, хотя существует множество сценариев и проектов, пытающихся ее упростить. Тем не менее, моя личная рекомендация — убедиться, что вы понимаете, что происходит за кулисами, если вы используете один из этих методов.
Давайте начнем с некоторых наиболее популярных проектов для включения Systemd в WSL:
Я лично не запускал ни один из них, но все они с открытым исходным кодом, и я просмотрел исходный код, чтобы сравнить методы. По сути, каждый из них создает новое пространство имен или контейнер, в котором Systemd может работать как PID 1.
Вы можете увидеть это в действии, выполнив следующие действия:
Бег:
sudo -b unshare --pid --fork --mount-proc /lib/systemd/systemd --system-unit=basic.target
Это запустит Systemd в новом пространстве имен с собственным отображением PID. Внутри этого пространства имен Systemd будет PID1 (как и должно быть для работы) и будет владеть всеми остальными процессами. Однако «настоящее» отображение PID по-прежнему существует за пределами этого пространства имен.
Обратите внимание, что это «минимальная» командная строка для запуска Systemd. Он не будет поддерживать, по крайней мере:
- Windows Interop (возможность запуска Windows
.исполняемый
)
- Windows PATH (который в любом случае не нужен без Windows Interop)
Сценарии и проекты, перечисленные выше, выполняют дополнительную работу, чтобы заставить эти вещи работать.
Подождите несколько секунд, пока Systemd запустится, затем:
sudo -E nsenter --all -t $(pgrep -xo systemd) runuser -P -l $USER -c "exec $SHELL"
Это входит в пространство имен, и теперь вы можете использовать пс -efH
увидеть это системад
работает как PID 1 в этом пространстве имен.
На этом этапе вы должны быть в состоянии запустить systemctl
.
И после того, как вы доказали себе, что это возможно, я рекомендую полностью выйти из экземпляра WSL, а затем выполнить wsl --terminate <дистрибутив>
в теме. В противном случае у вас будут некоторые вещи «сломаны», пока вы их не сделаете. Вероятно, они могут быть «исправлены», но это выходит за рамки любого вопроса Ask Ubuntu ;-). Я рекомендую обратиться к проектам выше, чтобы увидеть, как они справляются с этим.