Memcached и Systemd
Memcached и systemd... Казалось бы, какая тут может быть проблема, однако проблема есть, и, установив memcached из репозиториев вашего дистрибутива или собрав его из исходных текстов, запустить memcached с помощью средств systemd не всегда удается.
В первом слуае, установив пакет с memcached из репозиториев дистрибутива, вы, вводя в терминал
systemctl start memcached
понимаете, что ничего не работает. Если это RedHat или Centos, то там причина в том, что дистрибьютор почему-то установил зависимость memcached от httpd. Зачем? Может мы хотим использовать memcached как хранилище данных для другого сервиса. Но фундаментальный недостаток юнита, который идет из коробки это то, что тип сервиса выставлен в "simple", что предполагает, что запускаемый процесс не будет порождать дополнительных процессов. memcached это делает. Это легко доказать при помощи strace:
strace -fce clone,fork,vfork,execve memcached -m 12
% time seconds usecs/call calls errors syscall
------ -------- ----------- ----- ------ -------
100.00 0.000002 2 1 execve
0.00 0.000000 0 5 clone
------ -------- ----------- ----- ------ -------
100.00 0.000002 6 total
Итак тип сервиса должен быть выставлен в "forking". Идем дальше. Устанавливая memcached на Debian, вы с ужасом узнаете, что запускать Debian его предполагает при помощи perl скрипта. А тип сервиса не указан вообще, что по-умолчанию откатывает нас на "simple", и снова ничего не работает.
Но мало просто установить тип сервиса в "forking" - для форкающихся процессов крайне желательно указать еще на PID-файл, который содержить interger значение PID'а головного (родительского) процесса. Это требуется для корретной остановки службы в случае необходимости. Не стоит забывать и о том, что разнообразные службы всё-таки не стоит запускать под пользователем root в целях собледения требований безопасности.
Ну не будем ходить вокруг да около, а просто приведем гарантированно рабочий текст unit-файла memcached, который позволяет нормально запускать его под systemd:
[Unit]
Description=memcached - memory object caching system
After=network.target
[Service]
Type=forking
PIDFile=/var/run/memcached/memcached.pid
StandardOutput=journal
StandardError=journal
User=memcached
Group=memcached
EnvironmentFile=/etc/default/memcached
ExecStart=/usr/bin/memcached -vv $OPTIONS \
-P $PIDFILE \
-t $THREADS \
-m $STORAGE \
-c $MAXCONN
RuntimeDirectory=memcached
[Install]
WantedBy=multi-user.target
Поясним подробнее, что делает каждая директива:
- "Description=" устанавливает простое описание службы, которое можно будет увидеть в выводе команды "systemctl status memcached"
- "After=" устанавливает последовательность запуска юнитов, в нашем случае memcached бедт запусщен после подготовки сети к работе
- "Type=" устанавливает тот самый тип службы, который позволяет systemd корректно запускать, отслеживать статус и останавливать службу
- "PIDFile=" указывает, где служба будет хранить файл с номером головного процесса
- "StandardOutput=" перехватывает стандартный поток вывода службы и перенаправляет его в systemd-journald - стандартная служба логирования в systemd, чтобы логи можно было смотреть командой journalctl -ru memcached
- "StandardError=" перехватывает стандартный поток ошибок службы и перенаправляет его в systemd-journald - стандартная служба логирования в systemd, чтобы логи можно было смотреть командой journalctl -ru memcached
- "User=" указывает от имени какого пользователя запускать службу
- "Group=" указывает от имени какой группы запускать службу
- "EnvironmentFile=" указывает где брать значения переменных, указанных в "ExecStart="
- "ExecStart=" указывает, что и с какими опциями запускать
- "RuntimeDirectory=" создает папку в каталоге "/run" с указанным тут именем до старта службы. В нее мы попросим memcached поместить свой PID-файл
- "WantedBy=" устанавливает зависимость службы от другого юнита, чаще всего таргета. Требуется для автоматического запуска службы в случае перезагрузки.
Осталось взглянуть на "EnvironmentFile", чтоы понять какие значения будут присвоены переменным в "ExecStart="
cat /etc/default/memcached
OPTIONS="-d -l 127.0.0.1 -p 11211 -U 11211"
STORAGE="128"
MAXCONN="256"
PIDFILE="/run/memcached/memcached.pid"
THREADS="8"
Разумеется, вы в праве менять названия переменных, их значения, а можете вообще отказаться от переменных и жестко установить все параметры прямо в "ExecStart=". Однако такой подход нельзя назвать гибким. И помните, что размещать unit-файлы лучше всего в "/etc/systemd/system" так как, при обновлении пакеты с помощью пакетного менеджера вашего дистрибутива, юнит, размещенный в "/lib/systemd/system" будет скорее всего затерт. Файлы, размещенные в "/etc/systemd/system" имеют приоритет над файлами, размещенными в "/lib/systemd/system"