Mongod через systemd на Debian (wsl)

Решил я как-то перевести свой MongoDB на нормальные рельсы — чтобы управлялся через service, статус показывал, логи в journald писал, и вообще как у людей. До этого я его запускал вручную: 

mongod --config /etc/mongod.conf --fork --logpath /var/log/mongodb/mongod.log

Работало, но статус непонятно какой, и каждый раз при старте системы нужно было не забыть запустить. Неудобно.

Думаю: сейчас сделаю sudo systemctl enable mongod, потом sudo systemctl start mongod, и живи спокойно. Ага, щас.

Первая попытка — фиаско с логами

Запускаю

sudo systemctl start mongod 

Смотрю статус — failed.

sudo systemctl status mongod 

Вижу какую-то кракозябру: code=exited, status=1/FAILURE. Непонятно, лезу в полный лог сервиса:

sudo journalctl -u mongod -n 30 

А там чётко написано:

Failed to open /var/log/mongodb/mongod.log

Ну, думаю, классика. Раньше я запускал mongod от своего пользователя, и файл лога создался с правами seligoroff:seligoroff. А сервис пытается работать от пользователя mongodb. Он туда просто не может писать.

Исправляю:

sudo chown -R mongodb:mongodb /var/log/mongodb

Отлично, думаю, теперь-то всё поедет.

Снова

sudo systemctl start mongod 

Смотрю статус — опять failed, но теперь ошибка status=14. И в journalctl — пусто, даже фатальной строки нет. Странно.

Вторая попытка — ошибка стала загадочной

status=14— что за зверь? Гуглю, нахожу что-то про проблемы с доступом к данным или сокетам. Проверяю /var/lib/mongodb — права все на mongodb, lock-файла нет.

sudo netstat -tulpn | grep 27018

Порт 27018 свободен. Ничего не горит.

Тогда решаю пойти старым дедовским способом — запустить mongod вручную, но от того же пользователя, от которого работает сервис, и без –fork, чтобы все ошибки вывалились в консоль.

Пишу:

sudo -u mongodb mongod --config /etc/mongod.conf

И… тишина. Просто возвращает управление. Процесса нет. Что за чертовщина?

Тогда добавляю –fork и временный лог-файл:

sudo -u mongodb mongod --config /etc/mongod.conf --fork --logpath /tmp/mongod_manual.log

Вижу сообщение: child process failed, exited with 1. И совет — запустить без –fork. Понял, ловлю ошибку в логе:

sudo cat /tmp/mongod_manual.log

И тут — бинго! Среди обычных строк вижу:

Failed to unlink socket file /tmp/mongodb-27018.sock: Operation not permitted

Вот оно что! Оказывается, когда я раньше запускал mongod от своего пользователя, он создал в /tmp сокет-файл mongodb-27018.sock. А теперь сервис от пользователя mongodb пытается его удалить при старте, но у него прав нет. И тихо падает.

Решение — пять секунд

Удаляю этот бедный сокет ручками:

sudo rm -f /tmp/mongodb-27018.sock

Запускаю сервис:

sudo systemctl start mongod

Смотрю статус:

● mongod.service - active (running)

Ура! Заработало.

Что я вынес из этого

  • Если сервис падает с непонятным кодом — запускай процесс вручную от того же пользователя, под которым работает сервис, и без демонизации (–fork). Увидишь всю подноготную.
  • Не забывай про временные файлы. Сокеты в /tmp — тоже часть состояния, и они могут оставаться от прошлых запусков от другого юзера.
  • Права на логи — это только полбеды. Проверяй всё: и данные, и сокеты, и lock-файлы.

Теперь мой MongoDB стартует через systemd, логи пишет куда надо, и я наконец-то могу делать sudo systemctl status mongod и видеть, что всё ок. Спокойствие, только спокойствие.