Служба systemd: в доступе отказано
У меня есть новая служба systemd, которая не запускается с ошибкой "Отказано в доступе". Я купил Thinkpad L480. К сожалению, похоже, что проблема в том, что ядро не обнаруживает тачпад. Это здесь может быть решено путем
sudo sh -c 'echo -n "elantech" > /sys/bus/serio/devices/serio1/protocol'
Поскольку я не хочу делать это при каждом запуске, я создал службу systemd, которая работает не так, как ожидалось.
Мой touchpad_enabler.service является
[Unit]
Description=FooBar
[Service]
Type=oneshot
ExecStart=/usr/local/bin/enable_touchpad.sh
[Install]
WantedBy=default.target
Файл сценария просто
#!/bin/bash
echo -n "elantech" > /sys/bus/serio/devices/serio1/protocol
Но я также попробовал это с sh -c
версия. Я настроил разрешения через
sudo chmod 744 /usr/local/bin/enable_touchpad.sh
sudo chmod 644 /etc/systemd/system/touchpad_enabler.service
поэтому оба файла принадлежат пользователю root. Затем я включил его через
systemctl enable enable_touchpad.sh
Когда я вручную запускаю сервис через systemctl start touchpad_enabler.service
, он работает совершенно нормально, и тачпад работает как надо. Тем не менее, при запуске службы происходит сбой и отображается как "сбой" в systemctl list-units
,
Выход из journalctl -b -u touchpad_enabler.service
является:
systemd[1]: Starting Solves bug that Thinkpad L480 Touchpad is not correctly detected...
enable_touchpad.sh[516]: sh: /sys/bus/serio/devices/serio1/protocol: permission denied
systemd[1]: touchpad_enabler.service: Main process exited, code=exited, status=1/FAILURE
systemd[1]: touchpad_enabler.service: Failed with result 'exit-code'.
systemd[1]: Failed to start FooBar
Похоже, проблема в разрешении на запись в сам файл. Но запуск службы вручную работает нормально, и, насколько я понимаю, systemd должен выполнить команду от имени пользователя root, верно?
От чтения man systemctl.service
У меня появилась идея добавить '+' к пути к файлу, чтобы он читал
ExecStart=+/usr/local/bin/enable_touchpad.sh
Без эффекта.
Я не очень понимаю, где это protocol
файл приходит из. Похоже, он создается ядром при запуске? Так что я также экспериментировал с After=
параметр, но systemd должен запускать службы после полной загрузки ядра, верно? Файл также принадлежит пользователю root, поэтому я не ожидаю никаких проблем.
Я надеюсь, что кто-то может помочь мне. Заранее спасибо.
2 ответа
Кажется, у вас немного запутаны файлы сервиса и скриптов. Кажется, что содержимое файлов должно работать.
Systemd нужен служебный файл. Поместите этот файл сюда
/etc/systemd/system/touchpad_enabler.service
С содержанием:
[Unit]
Description=FooBar
[Service]
Type=oneshot
ExecStart=/usr/local/bin/enable_touchpad.sh
[Install]
WantedBy=default.target
Затем ваш сценарий (я изменил имя, чтобы сделать разделение между служебным файлом и файлом сценария более четким. Также /usr/local/bin
это лучшее место, потому что оно обычно предназначено для локальных скриптов / программ)
/usr/local/bin/enable_touchpad.sh
И это будет иметь содержимое (без изменений):
#!/bin/bash
echo -n "elantech" > /sys/bus/serio/devices/serio1/protocol
Убедитесь, что права доступа к сценарию и служебному файлу верны. Они должны принадлежать пользователю root, а скрипт должен быть исполняемым.
sudo chmod 744 /usr/local/bin/enable_touchpad.sh
sudo chmod 644 /etc/systemd/system/touchpad_enabler.service
Затем вы включаете сервис systemd.
sudo systemctl enable touchpad_enabler.service
Это включает службу, поэтому она будет работать при загрузке. Его также можно запустить вручную с помощью:
sudo systemctl start touchpad_enabler.service
или вы можете напрямую запустить скрипт, минуя сервис systemd:
sudo /usr/local/bin/enable_touchpad.sh
Я не могу говорить об ошибке или о том, когда создается файл протокола, но служба должна работать.
РЕДАКТИРОВАТЬ:
Вы можете добавить After=
параметр к [Unit]
раздел службы, чтобы убедиться, что он работает после определенной цели, как default.target
или же multi-user.target
, По умолчанию каждый сервис зависит от sysinit.target
, поэтому я не уверен, насколько это будет иметь значение в вашем случае.
Если вы посмотрите здесь, https://stackoverflow.com/questions/27511139/how-to-make-sysfs-changes-persistent-in-centos-7-systemd, есть другие способы выполнить то, что вы хотите без специальной службы, Может быть, вы можете попробовать правило udev.
У меня та же проблема в моей службе высокой доступности postgresql с именем: «Patroni». Поэтому я просто закомментирую строки пользователя и группы, как показано ниже:
[Service]
Type=simple
#User=postgres
#Group=postgres
ExecStart=/root/.local/bin/patroni /etc/patroni.yml
А затем перезагрузите новую конфигурацию:
systemctl daemon-reload;
systemctl start <service>
Просто это!