neděle 5. ledna 2014

Vylepšíme si vyhledávání souborů v prostředí Unity

Již jsem psal o tom, že Unity, konkrétně Unity Files Lens mající na starost vyhledávání souborů a složek z Dashe, používá konzolový příkaz locate a nepoužívá ho zrovna efektivně. Používá totiž systémovou databázi, která obsahuje statisíce pro Unity irelevantních záznamů a když dojde na hodně často se vyskytující řetězce, výsledky kvůlli výkonu šulí a často nedostanete to, co byste dostat měli. Například, když napíšu "ink", vyplivne databáze 2689 záznamů, přičemž Unity z toho zajímají pouze 3. A protože nejsou mezi prvními 128 v seznamu, nedostanu nic. Ale zato rychleji. To, že někdy něco dostanete, má na svědomí Zeitgeist, ten se o souboru dozví ve chvíli, kdy ho v systému otevřete. Pokud ale "šmíráka" Zeitgeista zakážete v nastavení soukromí, může být občas vyhledávání opravdu problematické. Navrhl jsem minule i řešení, ale nedotáhl jsem to do konce, takže když na to zas přišla řeč, rozhodl jsem se to doklepnout a prakticky ukázat, jak to převést do praxe. ...

Pokud nebudeme upravovat zdroják Unity, bude potřeba mu podstrčit vlastní upravený příkaz locate, který bude nasměrovaný na novou databázi, očištěnou od nepotřebných souborů, které v tuto chvíli zdržují a limitují. Také je potřeba vytvořit adekvátní náhradu příkazu updatedb, která onu databázi vyrobí.

Prvním nápadem bylo zapsat do /etc/profile.d/ skript, který by uživatelům příkazy locate a updatedb nahradil patřičnými funkcemi. Ovšem to má hned dvě překážky. Profile skripty se spouští pouze s login shellem a Dash navíc neumí funkce exportovat, takže je potomci nezdědí. Bash to sice umí (musel by se použít soubor bashrc), ale ten je nám na nic, protože Unity spouští externí programy v systémovém shellu (/bin/sh), což je v Ubuntu právě Dash.

Druhý nápad je méně systémový a je potřeba ho aplikovat pro každého uživatele zvlášť, ale zase je to úkon extrémně jednoduchý, bezpečný a především funkční. Jednoduše hodíme do $HOME/bin/ skripty nazvané locate a updatedb, které překryjí ty systémové. Protože se tento adresář přidává do systémové proměnné $PATH na začátek (v Ubutnu se tak děje automaticky po přihlášení uživatele, pokud existuje - je to v profile skriptu) najde ho shell dříve, než ten systémový a také ho použije.

Update: Nakonec by vlastně šlo použít i ten profile k tomu, aby každému uživateli zkontoloval a případně vytvořil ~/bin se skripty, i aktualizoval databázi.. Ještě to otestuju..

Vyrobíme si tedy zmíněné skripty, šoupneme je do $HOME/bin/ a nastavíme příznak pro spustitelnost.

updatedb
#!/bin/sh
/usr/bin/updatedb -l 0 -o "$HOME/.locate.db" -U $HOME --prunepaths\
 "$(find $HOME -maxdepth 1 -type d -regex ".*/\..*" |\
 sed 's/ /\\ /g' | tr '\n' ' ')" $@

Jednoduchý skriptík, který vytvoří a aktualizuje lokální databázi obsahující pouze soubory z uživatelova domovského adresáře, přičemž vynechá skryté adresáře v první úrovni $HOME. Nic vám nebrání si seznam zakázaných adresářů vygenerovat podle svých potřeb. Unity stejně následně filtruje všechny skryté soubory, tak by bylo logické je z databáze vyřadit všechny. Ovšem to by mohla být u narvanějších houmů velká brzda, protože find by musel při každé aktualizaci nejprve rekurzivně celý $HOME prolézt a profiltrovat. Mé řešení je kompromisem, ale rychlým a na mém systému dodtatečně efektivním.

Databázi je třeba samozřejmě aktualizovat. To se stane kdykoliv napíšete příkaz updatedb do teminálu, ale rozumné je nechat ji aktualizovat automaticky alespoň jednou denně. Anacron se na spouštění uživatelských skriptů příliš nehodí a tak je možné přidat příkaz do aplikací spouštěných po přihlášení do systému, a/nebo to nacpat do cronu třeba na každou hodinu. Na mém systému trvá první vytvoření databáze s 894 soubory (z celkového počtu 37911) maximálně 8-27 ms (milisekund) a běžná aktualizace 6 ms, takže o nějakém zdržování nemůže být řeč, klidně bych mohl databázi aktualizovat při každém otevření Dashe.

locate
#!/bin/sh
/usr/bin/locate -d "$HOME/.locate.db" $@

Na hotovou databázi nasměrujeme nový příkaz locate. Pomocí proměnné $@ hodíme na konec našeho příkazu (stejně jako v případě updatedb) všechny argumenty, se kterými byl volán a všechny další přepínače a parametry budou samozřejmě fungovat normálně, jen ta databáze se použije jiná. V případě, že by odkazovaná databáze neexistovala, vyhodí locate chybu a nebude fungovat.

Download: locate-unity.tar.gz
Pokud se vám s tím nechce vyrábět ručně, zde najdete hotové skripty v jednom balení. Stačí stáhnout, rozbalit do $HOME/bin/ (pokud jste ho teprve nově vytvořili, odhlašte se a znovu přihlašte), spustit příkaz updatedb, zařídit jeho automatické periodické spouštění a hotovo.

Závěrem
Upozorňuji, že tímto postupem vyměníte příkaz locate celému uživatelskému účtu, takže pokud by se náhodou našla jiná aplikace, která by locate využívala (bez udání celé cesty), dostane to samé, jako Unity. Pokud budete chtít v terminálu použít neomezený locate můžete tak učinit přes sudo, nebo pod rootem a pod uživatelem si třeba můžete dát do ~/.bashrc alias pro /usr/bin/locate, aby se to používalo přívětivěji. Když se vám to přestane líbit, stačí jen vytvořené skripty smazat.

No a pokud máte nějakou kritiku, nebo vylepšení, sem s ním!

Žádné komentáře:

Okomentovat

Zkuste prosím při komentováni používat místo volby Anonymní volbu Název/adresa URL, kde vyplníte nějakou přezdívku, adresu zadávat nemusíte. Vědět, které příspěvky jsou od jednoho člověka, je fajn. Díky.

Pokud by se vám náhodou odeslaný komentář na stránce nezobrazil, vytáhnu ho z koše hned jak si toho všimnu. I Google spam filter se občas sekne.