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!