Marco's Blog

All content personal opinions or work.
en eo

Surviving a Catastrophic IMAP (Cyrus) Crash

2006-05-31 2 min read Howto marco

In a similar post I described what to do in case your IMAP server crashes and it still behaves well. This time, though, Cyrus crashed and burned beyond recognition, and there was nothing I could do to save the databases. All utilities in the books simply told me the db files were corrupt, and I should run recovery. I ran recovery, and nothing happened…

This time I found a two-way approach helped a lot: first, I instituted nightly backups of my email server, and keep the last three days, three weeks, and three months on file. I created a script (attached below) in TCL to do the trick.

Secondly, I figured that the only way to have a working database again was to uninstall and reinstall cyrus-imapd. I didn’t quite trust a blind reinstall (especially since it had cost me days to get the configuration just right). So I followed the following ’easy’ steps to get to a working system…

  1. FIRST AND FOREMOST: THIS IS NOT PROFESSIONAL ADVICE AND YOU SHOULD NOT RELY ON IT. CONSIDER IT A STARTING POINT FOR YOUR EXPLORATION, BUT IN NO CASE ACT UPON IT IF YOUR DATA IS IMPORTANT.
  2. STOP Cyrus: /etc/init.d/cyrus stop (maybe your distribution says cyrus-imapd or such)
  3. BACK UP YOUR DATA: cp -a /var/lib/imap /tmp/var_lib_imap
  4. FIND THE RPM: export rpmfile=locate cyrus-imapd | grep rpm | tail -1
  5. UNPACK THE RPM IN A TEMPORARY LOCATION: rpm -i –relocate /=/tmp $rpmfile
  6. REMOVE THE DB FILES YOU ARCHIVED: rm -rf /var/lib/imap
  7. COPY THE DB FILES INTO THE DESTINATION: cp -a /tmp/var/lib/imap /var/lib/imap
  8. START Cyrus: /etc/init.d/cyrus start

That should have fixed your problems. Stop Cyrus, and import all your email using the script in {moscontentlink:Recovering from IMAP Crash}.

[Script: backupimapdb.tcl]

#!/usr/bin/tclsh

variables

set bkdir /root/backup
set imapdir /var/lib/imap
set today [clock format [clock seconds] -format %Y-%m-%d]
set monthly [string match *-01 $today]
set weekly [expr [clock format [clock seconds] -format %w] == 0]

perform today’s backup

exec tar cvzf $bkdir/imapdb-daily-$today.tgz $imapdir

and the other ones if appropriate

if {$weekly} {
file copy -force $bkdir/imapdb-daily-$today.tgz $bkdir/imapdb-weekly-$today.tgz
}
if {$monthly} {
file copy -force $bkdir/imapdb-daily-$today.tgz $bkdir/imapdb-monthly-$today.tgz
}

get lists of backups

set daily [glob -nocomplain /root/backup/imapdb-daily-*]
set weekly [glob -nocomplain /root/backup/imapdb-weekly-*]
set monthly [glob -nocomplain /root/backup/imapdb-monthly-*]

analyze what can go: start with daily

proc deleteus files {
if {[llength $files] > 3} {
foreach file [lrange $files 0 [expr [llength $files -4]]] {
file delete -force $file
}
}
}
deleteus $daily
deleteus $weekly
deleteus $monthly