LINUX.ORG.RU

PulseAudio, systemd и все-все-все

 , , ,


0

2

Синопсис: недавно перешёл на «новые» технологии: чистую ALSA на PulseAudio, потому что в какой-то момент ALSA сломалась, а настраивать заново её желания никакого не было + фичи PA из коробки понравились (например, заработал звук уведомлений pidgin'а).

Также решил заменить строчки в .xinitrc с запуском emacs --daemon, mpd и mpdas (да-да, я пускал их только при старте иксов) на юнит-файлы для systemd --user.

Проблемы: после таких перестановок начались проблемы, стандартные и не очень:

  • Иногда заикается звук в mpd, как будто вернулся в эпоху поцарапанных CD.
  • Время от ввода пароля при логине в консоли до промпта стало 30 (!) секунд. Оно и раньше оставляло желать лучше (кстати, почему?), но именно после перехода на systemd --user в качестве автозапуска, оно увеличилось до 30 секунд.
  • Проблемы с D-Bus'ом (тоже появились после «перехода» на systemd):
    • не запускается mpdas: <20:45>[~] systemctl start --user mpdas Failed to get D-Bus connection: No such file or directory
    • И (видимо тоже из-за D-Bus'а) не работает пульса: звук есть, НО не работают команды для mute, увеличения и уменьшения громкости, а pavucontrol пишет следующее, а само PA пишет вот что:
      <20:50>[~] pulseaudio 
      E: [pulseaudio] socket-server.c: bind(): Address already in use
      E: [pulseaudio] module.c: Failed to load module "module-esound-protocol-unix" (argument: ""): initialization failed.
      E: [pulseaudio] main.c: Module load failed.
      E: [pulseaudio] main.c: Failed to initialize daemon.
      <20:56>[~] pulseaudio -k
      E: [pulseaudio] main.c: Failed to kill daemon: No such process
      

Конфигурация:

[*]Модель ноутбука -- HP Pavilion dv6-6c05er
[*]Система -- ArchLinux
[*]Версия systemd -- 222
[*]Версия PulseAudio -- 6.02
[*]Версия D-Bus -- 1.8.18
[*]login-shell -- zsh

Мысли о том, как решить: мне кажется, что загрузка при логине увеличилась из-за того, что login ждёт, пока systemd всё запустит, но ведь оно должно делать это параллельно и не задерживать логин (ведь так?)

nice у пульсы стоит -11, что вроде соответсвует высокому приоритету. Возможно проблема с IO, но в когда mpd заикается, никаких нагрузок на IO не происходит. Может быть надо как-то настраивать PulseAudio под своё железо?

Обращаюсь к знатокам systemd, пульсы и всего остального: как решить все эти проблемы?

sudo cast intelfx

P.S. «Активно» пользоваться пульсой и системд стал относительно недавно — прошу не пинать за незнание каких-то базовых принципов.


Поехали.

Время от ввода пароля при логине в консоли до промпта стало 30 (!) секунд. Оно и раньше оставляло желать лучше (кстати, почему?), но именно после перехода на systemd --user в качестве автозапуска, оно увеличилось до 30 секунд.

При первом логине PAM-стек (через модуль pam_systemd.so) запускает инстанс systemd --user (к слову, этот инстанс общий для всех сессий одного пользователя) и ждёт достижения в нём basic.target (а может, и default.target).

Тридцать секунд — это время таймаута запуска сервиса. Следовательно, какой-то из твоих собственноручно написанных юнитов для systemd --user таймаутится при запуске и прибивается. Причина этому практически всегда одна: неправильный Type=.

Иногда заикается звук в mpd, как будто вернулся в эпоху поцарапанных CD.

Это для отдельного треда. Гугли tsched=0, увеличение размера буфера в ALSA (особенно если ядро сам собирал) и так далее. И обновляй ядро.

не запускается mpdas:
<20:45>[~] systemctl start --user mpdas Failed to get D-Bus connection: No such file or directory

Так mpdas не запускается или у тебя вообще сессионная дбас-шина свалилась к хренам?

echo $DBUS_SESSION_BUS_ADDRESS
pgrep -u $USER dbus-daemon
busctl --user
DBUS_SESSION_BUS_ADDRESS= systemctl --user
systemctl status user@$UID

(NB: это не пошаговое руководство к починке, а просто набор диагностических команд, вывод которых было бы неплохо увидеть.)

И (видимо тоже из-за D-Bus'а) не работает пульса: звук есть, НО не работают команды для mute, увеличения и уменьшения громкости, а pavucontrol пишет следующее, а само PA пишет вот что:
<20:50>[~] pulseaudio
E: [pulseaudio] socket-server.c: bind(): Address already in use

Ты как пульсу запускаешь? И, что важнее, — сколько раз? :]

(NB: пульса дбас практически не использует. То есть, использует, конечно, но pactl, pacmd, pavucontrol и собственно воспроизведение звука должны работать и без связи с пульсой через дбас.)

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от intelfx

Вот все сервисы, которые стартуют при логине: тыц. Причем и emacs и mpd стартуют хорошо, а mpdas не стартует вообще (честно говоря, при каком-то ребуте он у меня запустился, а потом опять перестал).

Так mpdas не запускается или у тебя вообще сессионная дбас-шина свалилась к хренам?

Я так понимаю, что сам D-Bus

<21:35>[~] echo $DBUS_SESSION_BUS_ADDRESS

<21:35>[~] pgrep -u $USER dbus-daemon 
1314
1522
<21:35>[~] busctl --user
Failed to connect to bus: No such file or directory
<21:35>[~] DBUS_SESSION_BUS_ADDRESS= systemctl --user
Failed to get D-Bus connection: Connection refused
<21:36>[~] systemctl status user@$UID
● user@1000.service - User Manager for UID 1000
   Loaded: loaded (/usr/lib/systemd/system/user@.service; static; vendor preset: disabled)
   Active: active (running) since Thu 2015-07-23 20:35:00 MSK; 1h 1min ago
 Main PID: 807 (systemd)
   Status: "Startup finished in 32.290s."
   CGroup: /user.slice/user-1000.slice/user@1000.service
           ├─807 /usr/lib/systemd/systemd --user
           ├─820 (sd-pam)
           ├─mpd.service
           │ ├─825 /usr/bin/mpd --no-daemon
           │ └─863 /usr/bin/pulseaudio --start --log-target=syslog
           └─emacs.service
             └─841 /usr/bin/emacs --daemon

Jul 23 20:34:59 HPdv6 emacs[826]: Company back-end 'company-auctex' could not ...d:
Jul 23 20:34:59 HPdv6 emacs[826]: Symbol's function definition is void: compan...ex
Jul 23 20:34:59 HPdv6 emacs[826]: Company back-end 'company-math' could not be...d:
Jul 23 20:34:59 HPdv6 emacs[826]: Symbol's function definition is void: compan...th
Jul 23 20:34:59 HPdv6 emacs[826]: Starting Emacs daemon.
Jul 23 20:35:00 HPdv6 systemd[807]: Started Emacs daemon.
Jul 23 20:35:00 HPdv6 systemd[807]: Reached target Default.
Jul 23 20:35:00 HPdv6 systemd[807]: Startup finished in 32.290s.
Jul 23 20:35:00 HPdv6 systemd[807]: Starting Default.
Jul 23 20:35:00 HPdv6 systemd[1]: Started User Manager for UID 1000.
Hint: Some lines were ellipsized, use -l to show in full.
<21:36>[~]

Ты как пульсу запускаешь? И, что важнее, — сколько раз? :]

Честно говоря, я её вообще не пускаю. :) При установке пакета она сама стала запускаться (а может я просто забыл). Но в htop она значится как потомок systemd --user

(NB: пульса дбас практически не использует. То есть, использует, конечно, но pactl, pacmd, pavucontrol и собственно воспроизведение звука должны работать и без связи с пульсой через дбас.)

Для регулирования громкости использую sxhkd со следующими строками в конфиге:

XF86AudioMute
     pactl set-sink-mute 1 toggle

XF86AudioRaiseVolume
     sh -c "pactl set-sink-mute 1 ; pactl set-sink-volume 1 +5%"

XF86AudioLowerVolume
     sh -c "pactl set-sink-mute 1 ; pactl set-sink-volume 1 -5%" 
В ручную из терминала тоже не работает. Остальные хоткеи (через sxhkd) работают хорошо.

vanzef ()
Ответ на: комментарий от vanzef

Я так понимаю, что сам D-Bus
<21:35>[~] echo $DBUS_SESSION_BUS_ADDRESS

Похоже, я понял. У тебя просто переменные окружения сессионные куда-то пропадают. В частности — XDG_SESSION_ID, XDG_RUNTIME_DIR, DBUS_SESSION_BUS_SOCKET. Как ты логинишься, запукаешь графику и так далее?

Честно говоря, я её вообще не пускаю. :) При установке пакета она сама стала запускаться (а может я просто забыл). Но в htop она значится как потомок systemd --user

А пульса у тебя запускается первым клиентом, который её использует. Это неправильно.

echo > /etc/xdg/autostart/pulseaudio.desktop

Потом выставляешь в /etc/pulse/client.conf параметр autospawn = no.

Потом разбираешься с systemd --user (точнее, с переменными окружения, которые куда-то пропадают) и делаешь systemctl --user enable pulseaudio.

Наконец, насчёт mpdas. В его юнит-файле у тебя WantedBy=multi-user.target. Это неправильно: в пользовательском режиме такого таргета нет (по крайней мере, пока ты его сам не создашь и не воткнёшь в загрузку). Там нужно default.target.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Как ты логинишься, запукаешь графику и так далее?

Логинюсь в tty, а графику запускаю через startx.

echo > /etc/xdg/autostart/pulseaudio.desktop
Потом выставляешь...

Сделал, но это не помешало пульсе самой запуститься, а вот включить через systemctl --user не могу — мешает D-Bus.

vanzef ()
Ответ на: комментарий от intelfx

Хотел ещё вот что спросить: при перезапуске какого-либо сервиса, зависимые перезапускаться должны?

Пример: если я перезапускаю D-Bus, то у меня падает NetworkManager и сам не восстанавливается.

vanzef ()
Ответ на: комментарий от vanzef

Логинюсь в tty, а графику запускаю через startx

Тогда тебе нужно разобраться в собственных скриптах и понять, в каком месте сбрасываются сессионные переменные.

И вот ещё: непосредственно после текстового логина (в самом начале) переменные XDG_SESSION_ID и XDG_RUNTIME_DIR установлены?

intelfx ★★★★★ ()
Ответ на: комментарий от vanzef

Вообще да, должны. Но:

  • это работает только для явно указанных в юните зависимостей, а зависимость от dbus никто явно не пишет (считается, что он есть всегда и везде);
  • перезапускать общесистемный dbus-daemon нельзя, потому что он не умеет сохранять своё состояние (теряются все соединения), а к общесистемной шине подключен даже сам systemd.
intelfx ★★★★★ ()
Ответ на: комментарий от intelfx

Тогда тебе нужно разобраться в собственных скриптах и понять, в каком месте сбрасываются сессионные переменные.

Ну, я вообще впервые слышу об этих переменных и в скриптах их не трогаю (явно уж точно).

И вот ещё: непосредственно после текстового логина (в самом начале) переменные XDG_SESSION_ID и XDG_RUNTIME_DIR установлены?

Только что проверил, их нет. Вообще не существуют.

P.S. D-Bus работает через раз, в прошлую загрузку он был и я смог сделать systemctl --user enable pulseaudio. Это правильный результат: pulseaudio --daemonize=no как потомок systemd --user?

vanzef ()
Ответ на: комментарий от vanzef

Только что проверил, их нет. Вообще не существуют.

Тогда грепни pam_systemd.so по всем файлам в директории /etc/pam.d.

Хотя если это арч, то я просто не представляю, как его нужно сломать, чтобы потерять сессионные переменные.

Это правильный результат: pulseaudio --daemonize=no как потомок systemd --user?

Необходимый, но недостаточный. Нужно удостовериться, что оно дежит в правильной контрольной группе (systemd-cgls).

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Тогда грепни pam_systemd.so по всем файлам в директории /etc/pam.d.

Есть только в файле system-login:

<23:35>[~] for i in $(ls /etc/pam.d); do echo $i && cat /etc/pam.d/$i | grep pam_systemd; done 
...
system-login
-session   optional   pam_systemd.so

Нужно удостовериться, что оно дежит в правильной контрольной группе (systemd-cgls).

Пульса находится в

system.slice -> user.slice ->
user-1000.slice -> user@1000.service ->
pulseaudio.service -> /usr/bin/pulseaudio --daemonize=no

vanzef ()
Ответ на: комментарий от vanzef

Всё правильно.

Тогда я просто не знаю, что у тебя не так с дбасом. Вышеуказанный pam_systemd.so должен задавать все эти переменные для каждого login shell (точнее, для каждого session leader).

intelfx ★★★★★ ()
Ответ на: комментарий от intelfx

Вот сейчас система загрузилась с рабочим D-Bus'ом и эти переменные есть. Надо попробовать убрать все юниты для systemd --user

vanzef ()
Ответ на: комментарий от vanzef

Попробуй убрать и добавлять по одному. Начни с пульсы. И потом сразу же проверь — есть ли сессионные переменные; есть ли доступ к пульсе из иксовых программ; не висит ли система перед логином.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от vanzef

Я плюс-минус понял, в чём могло быть дело.

30 (точнее, 25) секунд — это не таймаут запуска сервиса (я идиот, он 90 секунд), а таймаут вызова по шине D-Bus. При этом pam_systemd.so работает так: пинает по шине logind, чтобы тот создал сессию и запустил systemd --user, ждёт запуска и уже потом устанавливает сессионные переменные.

Если systemd --user висит, происходит таймаут вызова и pam_systemd.so отваливается, не создав сессию и не установив никаких переменных.

А вот почему он висит — вопрос хороший. Наверное, всё-таки где-то налажано с Type= или ещё чем-то.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Методом проб и ошибок выяснил, что давало эти 25 секунд — emacs. Странно, учитывая что .service я брал с вики. Может ты знаешь, что не так? Теперь почти ничего не виснет, хотя всё равно какое-то время после строчки «Last login...» приходится ждать.

С переменными теперь всё в порядке, а вот tsched=0 не особо помог — один раз были глюки, хотя может быть они были из-за IO.

vanzef ()
Ответ на: комментарий от vanzef

Попробуй запустить emacs --daemon из консоли (до старта иксов, из ядерной консоли). Он «держит» консоль или отдаёт её сразу?

intelfx ★★★★★ ()
Ответ на: комментарий от vanzef

Ну и да,

всё равно какое-то время после строчки «Last login...» приходится ждать

systemd-analyze --user critical-chain.

intelfx ★★★★★ ()
Ответ на: комментарий от intelfx

Держит, причем достаточно долго. Можно его как-нибудь «распараллелить»?

systemd-analyze --user critical-chain
The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

default.target @1.579s
└─pulseaudio.service @1.548s
  └─basic.target @195ms
    └─paths.target @195ms

Видимо, тут проблема не в systemd.

vanzef ()
Ответ на: комментарий от vanzef

Смотри.

Во-первых, на моей системе ожидание systemd --user происходит до показа строчки «Last login...». Т. е. если у тебя оно висит после неё — либо ты что-то перенастраивал в PAM, либо это висит не systemd --user.

Во-вторых, если емакс некоторое время держит консоль, а потом, тем не менее, её отдаёт — то это, конечно, странно, но лечится следующим образом.

Выкидываешь из emacs.service секцию [Install] и пишешь вспомогательный сервис, скажем, start-emacs.service:

[Unit]
Description=Start Emacs asynchronously

[Service]
Type=oneshot
RemainAfterExit=false
ExecStart=/usr/bin/systemctl --user start --no-block emacs

[Install]
WantedBy=default.target
intelfx ★★★★★ ()
Ответ на: комментарий от intelfx

Впрочем, одна секунда — это всё равно дофига для пользовательского инстанса, и critical-chain почему-то не показывает то, что должен. Попробуй systemd-analyze --user blame.

(Собственно, вышеописанным способом можно запускать не только emacs, но и что-либо другое — просто допиши имена сервисов в строку systemctl.)

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Выкидываешь из emacs.service секцию [Install], ...

Точнее, так: выкидываешь из emacs.service секцию [Install], делаешь systemctl --user disable emacs, и дальше как написано.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

До изменения способа загрузки emacs'а, blame был пуст (но и emacs я не пускал через systemd).

Сейчас сделал, как ты написал, попробовал blame:

<21:01>[~] systemd-analyze --user blame
          9.451s emacs.service
            10ms start-emacs.service

vanzef ()
Ответ на: комментарий от vanzef

Это нормально. Главное, что default.target его не ждёт.

Значит, тормоза при логине (если они не исчезли) берутся откуда-то ещё.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от intelfx

Кстати, не можешь подсказать, как скармливать systemd переменные окружения? А то у меня emacs ghc-mod найти не может, потому что тот в $PATH

vanzef ()
Ответ на: комментарий от vanzef

Если в конкретном юните — Environment="NAME=VALUE" "NAME2=VALUE2" ... в секции [Service].

Если вообще глобально — DefaultEnvironment="NAME=VALUE" "NAME2 VALUE2" ... в /etc/systemd/user.conf.

Если глобально, но только на текущий запуск — systemctl --user set-environment "NAME=VALUE" "NAME2=VALUE2" ....

(В первых двух случаях кавычки можно опустить, если в значении нет пробелов. В последнем случае согласно правилам твоего шелла.)

Короче, читать сюда: systemd.exec(5), systemd-system.conf(5), systemctl(1).

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 3)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.