UniFi Cloud Key: Couldn’t get file length when opening mapping

В какой-то момент Unifi Cloud Key перестал логинить через веб-интерфейс. Оказалось проблема в том что MongoDB сломался.

Диагностика

Сперва не поняли почему перестало логинить. Попробовали зайти через ssh и хоть оно работает. Далее решили сбросить пароль по статье из Хабра но получил ошибку:

connecting to: 127.0.0.1:27117/ace
Mon Jun 15 14:01:29.769 Error: couldn't connect to server 127.0.0.1:27117 at src/mongo/shell/mongo.js:147
exception: connect failed

Попробовал рестартнуть сервис UniFi и опять таки получил ошибку, но journalctl -xe показал что это из-за таймаута NTP. Чо к чему. Поискал логи и нашел /srv/unifi/logs/server.log в котором обнаружил сообщение:

[initandlisten] MongoDB starting : pid=24179 port=27117 dbpath=/usr/lib/unifi/data/db 32-bit host=UniFi-CloudKey
[initandlisten]
[initandlisten] ** NOTE: This is a 32 bit MongoDB
[initandlisten] ** 32 bit builds are limited to less
[initandlisten] ** See http://dochub.mongodb.org/core/32bit
[initandlisten]
[initandlisten] db version v2.4.10
[initandlisten] git version: nogitversion
[initandlisten] build info: Linux hartmann 3.16.0-4-armmp-lpae #1 SMP Debian
[initandlisten] allocator: system
[initandlisten] options: { bind_ip: "127.0.0.1", dbpath: "/usr/lib/unifi/data/db", journal: true,
[initandlisten] journal dir=/usr/lib/unifi/data/db/journal
[initandlisten] recover begin
[initandlisten] recover lsn: 512571983
[initandlisten] recover /usr/lib/unifi/data/db/journal/j._38
[initandlisten] recover skipping application of section seq:493588491 < lsn:512571983
[initandlisten] recover skipping application of section seq:493647801 < lsn:512571983
[initandlisten] recover skipping application of section seq:493707131 < lsn:512571983
[initandlisten] recover skipping application of section seq:493766401 < lsn:512571983
[initandlisten] recover skipping application of section seq:493825721 < lsn:512571983
[initandlisten] recover skipping application of section seq:493885071 < lsn:512571983
[initandlisten] recover skipping application of section seq:493944361 < lsn:512571983
[initandlisten] recover skipping application of section seq:494003681 < lsn:512571983
[initandlisten] recover skipping application of section seq:494062981 < lsn:512571983
[initandlisten] recover skipping application of section more...
[initandlisten] recover /usr/lib/unifi/data/db/journal/j._39
[initandlisten] dbexception during recovery: 15923 couldn't get file length
[initandlisten] exception in initAndListen: 15923 couldn't get file length
dbexit:
[initandlisten] shutdown: going to close listening sockets...
[initandlisten] shutdown: going to flush diaglog...
[initandlisten] shutdown: going to close sockets...
[initandlisten] shutdown: waiting for fs preallocator...
[initandlisten] shutdown: lock for final commit...
[initandlisten] shutdown: final commit...
[initandlisten] shutdown: closing all files...
[initandlisten] closeAllFiles() finished
[initandlisten] shutdown: removing fs lock...
dbexit: really exiting now

Починка

Из логов ясно что не хватает файла ace_stat.2 но не понятно что это за файл. Если глянуть еще раз в статью на Хабре то закрадывается предположение что база данных UniFi по-умолчанию называется ace. Пробуем починить:

mongod --dbpath /usr/lib/unifi/data/db --repair

На что получаем ответ что в базе данных обнаружен журнал, а для 32 битных систем по-умолчанию не включено журналирование и мол он необходим для запуска:

mongod --dbpath /usr/lib/unifi/data/db --journal --repair

И снова ошибка. Нам пишут что —journal и —repair взаимоисключающие опции:

mongod --dbpath /usr/lib/unifi/data/db --journal

На что естественно получаем ту же ошибку о том что файла ace_stat.2 нет. Смотрим на всякий случай что еще есть в директории с базой:

root@UniFi-CloudKey:~# ls -l /usr/lib/unifi/data/db/
total 163888
drwxr-x--- 2 unifi unifi     4096 Feb 26 14:44 ace
-rw------- 1 unifi unifi 16777216 Jun 15 14:39 ace.0
-rw------- 1 unifi unifi 33554432 Jun 15 14:39 ace.1
-rw------- 1 unifi unifi 16777216 Jun 15 14:39 ace.ns
drwxr-x--- 2 unifi unifi     4096 Feb 26 14:44 ace_stat
-rw------- 1 unifi unifi 16777216 Feb 26 18:09 ace_stat.0
-rw------- 1 unifi unifi 33554432 Feb 26 18:09 ace_stat.1
-rw------- 1 unifi unifi 16777216 Feb 26 18:09 ace_stat.ns
drwxr-x--- 2 unifi unifi     4096 Mar  3 14:33 journal
drwxr-x--- 2 unifi unifi     4096 Feb 26 14:44 local
-rw------- 1 unifi unifi 16777216 Feb 26 18:09 local.0
-rw------- 1 unifi unifi 16777216 Feb 26 18:09 local.ns
-rw-r----- 1 unifi unifi        7 Feb 26 14:43 previous_version
-rw-r----- 1 unifi unifi        7 Feb 26 14:43 version

И видим ace_stat.1 от 26 февраля. Не долго думая:

cp /usr/lib/unifi/data/db/ace_stat.1 /usr/lib/unifi/data/db/ace_stat.2
mongod --dbpath /usr/lib/unifi/data/db --journal

И наконец-то есть запуск. Останавливаем и запускаем сервис UniFi:

ctrl+d
systemctl restart unifi

После чего все корректно запускается и теперь можем залогиниться в веб-интерфейс.