Since a recent burglary I have been using ZoneMinder to provide CCTV security for my house on my Ubuntu 12.04 machine. I noticed earlier today that zoneminder had stopped running over the weekend and when I tried to start the service again, I got the following error:
Starting ZoneMinder: Bareword "ZM_PATH_LOGS" not allowed while "strict subs" in use at /usr/share/perl5/ZoneMinder/Logger.pm line 153. BEGIN not safe after errors--compilation aborted at /usr/share/perl5/ZoneMinder/Logger.pm line 168. Compilation failed in require at /usr/share/perl5/ZoneMinder.pm line 34. BEGIN failed--compilation aborted at /usr/share/perl5/ZoneMinder.pm line 34. Compilation failed in require at /usr/bin/zmpkg.pl line 37. BEGIN failed--compilation aborted at /usr/bin/zmpkg.pl line 37. failure
Looking through the ZoneMinder code I discovered that the error indicated that a configuration variable somehow wasn't set. My first thought was that perhaps a new configuration variable had been added in an upgrade but hadn't been automatically added to the configuration file. So I added a line containing ZM_PATH_LOGS to /etc/zm/zm.conf but now when I tried to start zoneminder, I received a similar (but different error):
Starting ZoneMinder: Bareword "ZM_USE_DEEP_STORAGE" not allowed while "strict subs" in use at /usr/share/perl5/ZoneMinder/General.pm line 207. BEGIN not safe after errors--compilation aborted at /usr/share/perl5/ZoneMinder/General.pm line 226. Compilation failed in require at /usr/share/perl5/ZoneMinder.pm line 35. BEGIN failed--compilation aborted at /usr/share/perl5/ZoneMinder.pm line 35. Compilation failed in require at /usr/bin/zmpkg.pl line 37. BEGIN failed--compilation aborted at /usr/bin/zmpkg.pl line 37. failure
I added a line for this then another similar (but different) error appeared! Clearly this approach isn't correct. So I logged into mysql and had a poke around:
mysql -u XXX -p mysql> show databases; mysql> use zm; mysql> show tables; +----------------+ | Tables_in_zm | +----------------+ | Config | | ControlPresets | | Controls | | Devices | | Events | | Filters | | Frames | | Groups | | Logs | | MonitorPresets | | Monitors | | States | | Stats | | TriggersX10 | | Users | | ZonePresets | | Zones | +----------------+ 17 rows in set (0.00 sec) mysql> select * from Config; 0 rows in set (0.00 sec)
Like in iPhone adverts, the above sequence is shortened. But the surprising result appears at the end: there are no lines in the Config table! This must be the culprit preventing ZoneMinder from starting.
Its not clear how this config table has been reset, as I don't recall updating the ZoneMinder packages recently, so I don't think its a botched database upgrade. I have restarted the machine that it runs on a couple of times over the weekend so perhaps the database got corrupted at shutdown, though I can't find any mysql logs complaining about this. In conclusion, I don't know how it happened! But if it happens again all the info is here.
To resolve this, I download the ubuntu package for zoneminder and had a look in the postinst install script to see how it initialised the database. It turns out there is an sql file at /usr/share/zoneminder/db/zm_create.sql which is applied at package installation. I edited this file and removed all lines that didn't affect the Config table and applied it manually.
Finally zoneminder started up (albeit without my configurations)! After reconfiguring zoneminder, I noticed in ZoneMinder's log database the following entry:
Config mismatch, expected 218 items, read 0. Try running 'zmupdate.pl -f' to reload config.
If this happens again, perhaps 'zmupdate.pl -f' is sufficient to fix it, instead of error-prone sql hacking. (update: according to commenters this does not work!)
And the moral of the story is: always backup your databases!