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

133

Я только что обновил Ubuntu Server 14 до версии 15. У меня возникли проблемы с работой моего сценария upstart после обновления, и я прочитал, что systemd является новым значением по умолчанию. Я далеко не эксперт по Linux, поэтому, пожалуйста, будьте осторожны со мной :-)

Вот что мой сценарий выскочки был раньше:

description "NZBGet upstart script"

setuid robert
setgid robert

start on runlevel [2345]
stop on runlevel [016]

respawn

expect fork

script
    exec nzbget -D
end script

pre-stop script
    exec nzbget -Q
end script

Основываясь на вики-странице upstart для systemd , я использовал предоставленные там таблицы, чтобы как можно точнее отобразить вещи в моем новом файле службы systemd:

[Unit]
Description=NZBGet Service

[Service]
Type=forking
ExecStart=/usr/local/bin/nzbget -D
ExecStop=/usr/local/bin/nzbget -Q
Restart=on-failure

Этот файл находится по адресу /home/robert/.config/systemd/user/nzbget.service. Чтобы запустить сервис вручную, я делаю:

$ systemctl --user start nzbget

Это прекрасно работает. Однако, когда я выхожу из сеанса SSH, служба отключается. Кроме того, он не запускается при загрузке или входе пользователя в систему. Я хочу, чтобы он вел себя так же, как и сервис выскочки: я хочу, чтобы он запускался при загрузке, работал постоянно и как конкретный пользователь.

Что мне нужно сделать, чтобы получить эту конфигурацию?

void.pointer
источник

Ответы:

164

Первая проблема

Вы можете указать директивы User=и Group=в [Service]разделе файла модуля.

Вторая проблема

Чтобы служба запускалась при загрузке, не следует помещать ее в домашнюю папку. Вместо этого поместите это под /etc/systemd/system/. Это папка, предназначенная для использования системным администратором (то есть вами) для добавления новых общесистемных сервисов.

Другие папки включают в себя:

  • /usr/lib/systemd/system/Предназначен для пакетов, которые хотят установить файлы модулей, хотя в Debian и Ubuntu эта папка фактически /lib/systemd/system/потому, что различные папки binи libпапки еще не объединены в единый /usr/префикс.
  • /usr/local/systemd/system/ предназначен для установки модулей локально скомпилированными пакетами.

Тестирование устройства

Как только файл модуля окажется в соответствующем месте, вы можете сразу же запустить его, набрав systemctl start <UNIT_FILENAME>как обычно. Это должно работать без необходимости вводить полный путь к устройству. Расширение также не нужно указывать, если оно есть .service.

Включение устройства

Прежде чем вы сможете включить свой блок, вам нужно добавить [Install]раздел, в котором вы должны добавить директиву WantedBy=multi-user.target. Эта директива указывает этап процесса загрузки, на котором должна быть запущена служба (если она была включена). multi-user.targetподходит для большинства услуг.

Как только эта информация будет добавлена, вы можете использовать systemctl enable <UNIT_FILENAME>ее, чтобы включить модуль, и теперь systemd автоматически запускает его во время загрузки на указанном этапе.

Yamaho
источник
Это сработало. Я должен был указать абсолютный путь к имени файла службы в systemctl enableкоманде, хотя, это не было очевидно для меня сначала. Также включение дало мне предупреждение о пропаже [Install]раздела. Я проигнорировал это, но я не уверен, повлияет ли это на его способность запускаться во время загрузки.
void.pointer
2
InstallПредупреждение было на самом деле очень важно. Он не запускается при загрузке без WantedBy=multi-user.targetпод [Install]секцией. После добавления этого в .serviceфайл, то вы можете enableего.
void.pointer
4
Я прошу прощения за то, что оставил ответ без внимания в течение столь длительного времени. Я исправил место, куда должен идти файл модуля, добавил недостающую информацию о [Install]разделе. Надеюсь, теперь это более полезно для тех, кто ищет это.
Ямахо
5
Это становится намного проще , если имя пользователя является шаблонный, то есть ваша служба определяется с именем файла в формате something@.serviceзатем enableхотели something@username.serviceнастройки становится User=%iозначает , что пользователь не жестко закодированы и несколько пользователей могут использовать такое же определение. Пример.
Уолф
1
Это начнется, если я помещу это под /etc/systemd/user/?
Хуршид Алам
46

Возможно, вам будет интересно использовать функциональность systemd "задержка пользователя". Это включено через loginctl enable-linger USERNAME.

Это приводит к тому, что для соответствующего пользователя, запускаемого при загрузке, запускается отдельный диспетчер служб, поэтому ваши пользовательские блоки ~/.config/systemd/userбудут выбраны и обработаны во время загрузки и завершения работы в соответствии с конфигурацией вашей службы.

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

byteborg
источник
6
systemctl --userэто фантастическая находка. Спасибо!
Анвар
@byteborg Может быть, вы можете внести свой вклад в unix.stackexchange.com/questions/409900/… ? Мне нужна зависимость от PostgreSQL в длительной службе пользователей, но база данных остается системной службой, а не пользователем.
Михал Ф
1
Как только службы запущены, есть ли какие-либо методы, которые могут позволить пользователю просматривать журналы службы? Непривилегированный пользователь не сможет получить доступ к / var / log / syslog.
Мпр
2
Обратите внимание, что systemctl --user, похоже, не работает для сессий SSH.
Марк К Коуэн
2
Должно быть принято решение
Дрю