Вопрос или проблема
Я пытаюсь настроить fluidsynth
для работы как служба пользователя на системе Debian. Проблема в том, что он запускается при входе пользователя и нуждается в доступе к /dev/snd/seq
, иначе возникает ошибка, и он превращается в “зомби” (т.е. активен, но не действительно работает):
fluidsynth[2404]: ALSA lib seq_hw.c:466:(snd_seq_hw_open) open /dev/snd/seq failed: Permission denied
Этот доступ (в конце концов) предоставляется правилом udev 70-uaccess.rules
(которое выполняется 73-seat-late.rules
) — т.е. после успешного входа я могу перезапустить службу в терминале, и все работает.
Есть ли способ указать systemd запускать мою службу только после завершения выполнения этого правила?
Для поставленного вопроса (“ожидать завершения выполнения правил udev”) вы бы добавили зависимость от соответствующего .device
юнита:
Requires=dev-snd-seq.device
After=dev-snd-seq.device
Если бы не было .device юнита, вам нужно было бы добавить другое правило udev, которое применяет TAG+="systemd"
, чтобы заставить systemd сгенерировать виртуальный .device юнит.
Тем не менее, это не сработает, потому что ваш доступ не “(в конечном итоге) предоставляется правилом udev”. Правила udev обрабатываются только в ответ на события на самом устройстве, поэтому, хотя 73-seat-late.rules вызывает встроенную функцию udev ‘uaccess’, чтобы применить начальные ACL к помеченным устройствам, это происходит только один раз, когда создается событие add
для этого устройства (гораздо раньше вашего входа).
Правила для всех устройств не запускаются повторно, когда пользователь входит в систему, так как udev полностью не осведомлен о событиях “входа пользователя” (или любых не связанных с устройством событиях в общем). Вместо этого, после начальной обработки udev, доступ обрабатывается совершенно другой службой – конкретно, systemd-logind, – которая управляет отношениями пользователя и мест (сессиями) и использует libudev для перебора всех устройств с тегом "uaccess"
и обновления их ACL узлов устройства. На этом этапе она не переисполняет никаких правил udev.
Проблема в том, что systemd-logind делает это только после того, как он запустил менеджер сервисов пользователя (поскольку применение ACL является ‘функцией’ мест, поток кода должен создать ‘пользователя’, затем сессию(пользователь, место), и только потом информировать место о новой активной сессии), поэтому ваши сервисы на уровне пользователя, которые находятся в default.target
, вероятно, никогда не увидят обновление ACL вовремя. (Я вижу, что Fluidsynth 2.x уже поставляется с собственным user/fluidsynth.service
юнитом; я не уверен, как он должен работать, но подозреваю, что это зависит от того, чтобы пользователь находился в группе audio
и всегда имел доступ.)
Вам может потребоваться, чтобы служба запускалась другой целью (например, графической сессией), или добавить ExecStartPre=
, который просто будет циклически выполняться, пока у устройства не обновятся ACL.
ExecStartPre=/bin/sh -c "until [ -r /dev/snd/seq ]; do sleep 1; done"
Ответ или решение
Решение проблемы с запуском службы FluidSynth на системе Debian
При конфигурации службы FluidSynth для работы в пользовательском пространстве на системе Debian может возникнуть проблема с доступом к устройству /dev/snd/seq
. В случае, если служба запускается до завершения выполнения правил udev и обновления ACL, FluidSynth может выдать ошибку «Permission denied» и перейти в состояние «зомби». Для решения этой проблемы необходимо учесть некоторые аспекты работы системы и конфигурации служб.
Понимание механизма udev и systemd
Работа с устройствами в Linux управляется системой udev, которая отвечает за динамическую настройку прав доступа к устройствам. Ваша проблема заключается в том, что правила udev не перезапускаются при входе пользователя в систему; они обрабатываются только в ответ на события добавления устройств. Таким образом, необходимость в обновлении прав доступа к /dev/snd/seq
во время сеанса пользователя не будет выполнена, если служба FluidSynth запущена до этого.
Система systemd, в свою очередь, управляет сервисами и их зависимостями. Важно правильно настроить зависимости вашей службы FluidSynth, чтобы убедиться, что она не запустится до того, как необходимые ACL будут применены.
Предложения по исправлению
-
Установка зависимостей:
В вашем сервисном файле FluidSynth можно установить следующие зависимости, чтобы обеспечить правильный порядок запуска:Requires=dev-snd-seq.device After=dev-snd-seq.device
Это гарантирует, что служба FluidSynth не будет запущена до тех пор, пока устройство не будет готово.
-
Пользовательский сеанс и графические цели:
Если проблема остается актуальной, вы можете изменить целевую группу вашей службы. Рассмотрите возможность назначения службы в графическую сессию, которая обеспечит более поздний запуск, когда все необходимые ACL уже будут установлены. -
Проверка доступа в
ExecStartPre
:
Второй подход — добавление команды в секциюExecStartPre
вашего сервисного файла. Этот метод будет «ожидать» актуализации прав доступа к устройству, прежде чем пытаться его использовать:ExecStartPre=/bin/sh -c "until [ -r /dev/snd/seq ]; do sleep 1; done"
Это команда заставит систему пытаться получить доступ к устройству, пока оно не станет доступным.
-
Проверка принадлежности к группе audio:
Убедитесь, что пользователь, от имени которого запускается FluidSynth, принадлежит к группеaudio
. Это может потребоваться для того, чтобы FluidSynth мог получить доступ к звуковым устройствам. Добавьте пользователя в группу командой:usermod -aG audio username
Заключение
Внедрение предложенных решений позволит существенно улучшить взаимодействие вашей службы FluidSynth с устройствами звука на системе Debian. Правильная настройка зависимостей, ожидание актуализации ACL и проверка принадлежности к группе являются ключевыми шагами для устранения ошибок с правами доступа. Если вам потребуется дополнительная помощь по настройке или возникнут другие вопросы, всегда можно обратиться к сообществу пользователей Debian или специализированным форумам, посвящённым работе с systemd и udev.