Mbox mail file + maildir convert with mb2md + namazu fast search

Ez a fórum bejegyzésem alapján arra jutottam, hogy írok inkább egy saját script-et a problémámra.

Az alábbi volt a feladat amit magamnak állítottam: nagy (10 GB > méretű mbox fájlokban akartam gyorsan keresni, index-elt adatbázis alapján).

Úgy oldottam meg, hogy a script-em 2 paramétert fogad: 1) mbox fájl 2) keresett kulcsszó

A script-em átkonvertálja az mbox fájlt apró fájlokra maildir formátumba mb2md-vel, majd ezt leindexeli namazu-val, a végén rá keres az adatbázisra namazu-val a kulcsszó alapján.

Minden esetben hash alapján tárolom a temp könyvtárban az eredményeket, hogy többszöri futtatáskor is csak egyetlen egyszer kerül leindexelésre az egész anyag.

Az e-maileket elválasztva print-elem, színessel megjelölve a grep-ben a kulcsszót, plusz egy sorral lejjebb a from stb. tagokkal. Ha valakinek van ötlete a mégjobban átláthatóvá tételhez, szívesen veszem!

Jelenleg egy 8.3 GB-os mbox fájlon tesztelem, kb. 70 000 db e-mail. Egy 2 magos 2 x 2.4 Ghz-es gépen futtatom.

Sima grep futtatása a fájlon: 13 perc 6 másodperc.
A script első futása indexeléssel: 4 óra 13 perc.
Második futásra csak kereséssel: 0.13 másodperc.

maildir mérete 8.4 GB, index 234 MB lett (2.7 %).

Script itt a pastebin-en is

-------


#!/bin/bash

# written by Andras Horvath, han at log69.com - (2010) Public Domain

# CONVERT MBOX TO MAILDIR WITH MB2MD
# INDEX MAILDIR WITH NAMAZU
# SEARCH PATTERN IN DATABASE
# PRINT RESULTS AND THESE TAGS: FROM, TO, SUBJECT, DATE

# PARAMETERS
# 1) MBOX FILE
# 2) TEXT PATTERN TO SEARCH FOR

# DATA GETS INDEXED ONLY ONCE


if [ -z "$1" ]; then echo "error: no mbox file name given" >&2; exit 1; fi
if [ -z "$2" ]; then echo "error: no search pattern given" >&2; exit 1; fi

if ! which mb2md 1>/dev/null;  then echo "mb2md command missing" >&2;   exit 1; fi
if ! which mknmz 1>/dev/null;  then echo "mknmz command missing" >&2;   exit 1; fi
if ! which namazu 1>/dev/null; then echo "namazu command missing" >&2;  exit 1; fi


MBOX=$( readlink -f "$1" )
PATTERN="$2"

if ! [ -e "$MBOX" ]; then echo "error: mbox file doesn't exist" >&2; exit 1; fi

# creating unique dir name for one time indexing,
# hashing only some part of it, cause large files might slow things down
HASH=$( (du -sb "$MBOX" | grep -o "^[0-9]*"; head -n50 "$MBOX"; tail -n50 "$MBOX") \
    | md5sum | grep -o "^[^ ]*" )
# unique temp dir name depending on script changes,
# let's use new dir everytime the program is modified,
# dir structure might change with it too
TEMP="/tmp/"$( basename "$0" | grep -oE "^[^\.]*" )_$(md5sum "$0" | grep -o "^[^ ]*" )

HASHDIR="$TEMP"/"$HASH"
MAILDIR="$HASHDIR"/maildir
INDEXDIR="$HASHDIR"/index


# if hash dir exists in temp, it means we did a search already on this mbox,
# so we won't convert and index anything, only search
if ! [ -e "$HASHDIR" ]
then
	mkdir -p "$HASHDIR"
	mkdir -p "$MAILDIR"
	mkdir -p "$INDEXDIR"

	echo "--- converting mbox ---" >&2
	mb2md -s "$MBOX" -d "$MAILDIR"

	echo "--- rename all the weird maildir files ---" >&2
	DIR=$( pwd )
	cd "$MAILDIR"/cur
	COUNT="1"
	find -type f | while read NAME
	do
		mv "$NAME" "$COUNT"
		COUNT=$(( $COUNT + 1 ))
	done
	cd "$DIR"

	echo "--- indexing ---" >&2
	mknmz -O "$INDEXDIR" "$MAILDIR"/cur
fi

# search text pattern in database
echo "results:"
namazu -l "$PATTERN" "$INDEXDIR" | while read FILE; do
	echo "---"
	echo "$FILE"
	grep     --color -i "$PATTERN"   "$FILE"
	echo
	grep -m1 --color -i "^From: "    "$FILE"
	grep -m1 --color -i "^To: "      "$FILE"
	grep -m1 --color -i "^Subject: " "$FILE"
	grep -m1 --color -i "^Date: "    "$FILE"
	echo
done

Hozzászólások

Én onnantól tudok hozzászólni, hogy Maildir formátumra hoztad a levelesládát. (Én a távoli IMAP fiókomról készítek/frissítek lokális mentést, Maildir formátumban, az offlineimap-pal.)

Indexelésre és keresésre a recoll nevű Qt-s Xapian frontend-et használom. Ez a páros így egy csoda. A Maildir fán kívül leindexeltem vele a teljes SUSv4 HTML fát is, eszetlenül jól lehet így keresni.

A cucc használata két részből áll ugye (alapozva most már a meglévő lokális fára, ami lehet Maildir vagy HTML fa vagy akármi más a támogatott formátumok közül): indexelés és keresés. Mindkettőből van GUI és parancssoros is.

Az indexelés parancssorból a "recollindex" paranccsal történik, ami növekményesen (frissítve) indexel. A "recollindex -z" alapból újraépit. A recoll GUI-n pedig van ilyen menüpont (File|Update index) -- úgy gondolom, ez a növekményeset frissítést futtatja le.

A keresést a "recoll" programmal lehet végezni. A "recoll -t -q <query>" szöveges kimenetet ad (találati lista, elég könnyen parse-olhatónak tűnik). Azonban a fenti scripted alapján (mivel színez) úgy gondolom, hogy neked a recoll GUI is megfelelő volna, mivel a találati listát tartalomfüggő bejegyzésekkel tölti meg (vagyis az illeszkedő HTML file-ról más összegzést mutat, mint egy illeszkedő Maildir file-ról). Mind a HTML-nél, mind az email-nél van "preview" link az összegző bejegyzés mellett, ami nagyon jól jön. HTML-nél pedig "Open" link is van, ami a böngészőt ráugrasztja az adott helyi HTML file-ra.

A találati listát több szempont szerint lehet rendezni is (legalábbis a GUI-ban).

Most látom a debian csomag leírásában, hogy a recoll támogatja a mailbox formátumot közvetlenül is!

Több független fát (pontosabban konfigurációt) úgy lehet vele kezelni, hogy több konfig- (és abból következően index-) könyvtárat hozunk létre (a default a ~/.recoll), majd a -c kapcsolóval megadjuk az éppen használni kívántat a recoll(index)-nek. Hogy maga az indexelendő fa hol található, azt a konfigkönyvtáron belül adjuk meg. A fák elkülönítését én azért találtam hasznosnak, mert azt azért az elején el tudom dönteni, hogy a leveleimben, vagy a SUSv4-ben akarok-e keresni, és nem szeretném, ha a találatok keverednének. Így a legegyszerűbb külön indexeket fenntartani. A SUSv4 ráadásul nem is változik, így elég egyszer indexelni, és kész.

Ha egy kicsit turkálhatok még az eredeti problémában: úgy tűnik, hogy az mbox-aid archívumok, vagyis már nem változnak. Szerintem robbantsd szét az egészet egy maildir-ré (ez ideiglenesen rengeteg helyet fog pazarolni), majd a maildir-t gyömöszöld bele egy squashfs image-be! (A Lenny is támogatja.) Ezzel még az eredeti mbox-hoz képest is egy csomó helyet meg fogsz takarítani, ugyanakkor az egyes levelek file-szinten elérhetők lesznek (ha felcsatolod az image-et), vagyis tudni fogod indexelni és a találatokat egyenként nyitogatni.

A próba kedvéért most összenyomtam mksquashfs-sel a maildir-emet (alapértelmezett opciókkal): a maildir-nek a "du" által kijelzett helyfoglalásához képest a squashfs image 57.6%-ot foglal.

én meg az imap szerveren keresek.

Nem tudtam, de most látom, hogy az IMAP4 támogat szerveroldali keresést. Milyen klienst használsz? És a szerver tud előre indexelni (melyik szerver?), vagy amikor megkapja a keresőkifejezést, akkor kezd turkálni? Köszi.

(Pine-nal távoli IMAP szerveren keresni egy katasztrófa.)

mbox fájlt csplittel lehet triviálisan szétszedni.

Jogos; ha nem fontos a Maildir állománynév-szabályaihoz igazodni, és csak az számít, hogy minden levél külön file-ba kerüljön, akkor a csplit lehet a legjobb.

Köszi az alapos leírást. Nem csalódtam a tőled megszokott minőségben! :)

A Qt-s recoll GUI nagyon király, ha desktop index kellene, akkor ezt használnám. Sajnos a cli módja kicsit szegényes. A namazu-ban a -l kapcsolóval kapok legalább egy tiszta path-t a fájlhoz. Azért még eljátszok vele.

Magát a kereséseket folyamatosan használt mbox-okhoz használom, ezért a squashfs itt nem játszhat, de az ötlet tetszik! Az is igaz, hogy a használatban lévő mbox fálról kell egy copy-t csinálnom, nehogy közben nőljön a mérete. De ami a lényeg, hogy a maildir-rel már nagyon gyors.

Úgy látom a mai teszteléseimből, hogy beválik a script-em, pont azt csinálja amit szeretnék, és a namazu is baromi gyors, jelenleg nem sokat érnék vele ha más motort raknék be alá úgy gondolom.

Amit a jövőben be akarok állítani, hogy alapból maildir-es legyen a levelező szerver, így sima namazu-val, meg annak az index update-jével az index létrehozás is baromi gyors lenne. Igaz, a nagy mbox-okat meg learchiválom, szóval azért ennyire nem gond.

Szia.

Azt megkérdezhetem, hogy azért kerestél parancssoros programot mert nincs gui a szerveren, vagy más oka van? Mi a direkt erre a célra készült MailArchiva archiválót használjuk a levelezés archiválására, ahol a keresés webes felületen keresztül végezhető, képes a csatolmányok tartalmában is keresni és nincs szükség gui-ra a használatához.

Esetleg érdemes lehet kipróbálni, hátha bejön. Ha kérdésed lenne vele kapcsolatban, szívesen segítek.

Üdv: Zoli

Köszi a tippet, megnézem. Habár nem elsődleges az archiválás mint cél.

A parancssor azért kell nekem, mert úgy látom, hogy ezzel tudok a legproduktívabb lenni különböző okok miatt, pl. command history, screen session nagy puffer-e miatt, stdout kimenetének visszakereshetősége screen-ben, automatizálás at-vel vagy sleep paranccsal stb. Mindezek nagyban hozzájárulnak ahhoz a típusú munkámhoz, amit végzek. Ráadásul nagyon egyszerű, és sávszélesség takarékos is, ami sok esetben nagyon számít.

Közben elkezdtem használni recoll-t a saját notimon, leginkább a levelezésem indexelésére meg doksik-ra. Claws-mail-t használok MH fájlokkal, úgyhogy nagyon gyors az index update is.

A Qt-s gui nagyon jó, egyetlen dolgot sem tudnék kifogásolni benne, popup-kor is már fókusz van a beviteli mezőn, csak a szükséges menük, gyors stb. Az eredmények is nagyon áttekinthetőek a kulcszavak színkiemelésével, plusz a fájl típust jelző ikonok is nagyon beszédesek és szépek, a sima text és egyéb preview lehetőség is nagyon jó, az indexelés is nagyon gyors.

Egyszóval ezúton köszi még egyszer hogy megosztottad ezt a szuper progit! :)

Még egy megjegyzés: amikor hibaüzenetet vagy haladási infót írsz ki, akkor azt írd az stderr-re (

>&2

).