Softraid i autodetekcja

Zdarzyło mi się niedawno dołączyć dodatkowy dysk do działającego już systemu celem utworzenia redundancji na wszystkich partycjach (lub też na wolumenach LVM). Wszystko to działo się na Ubuntu 8.04 LTS, a więc prawie na debianie :-)

Całość procesu jest dość prosta i opisywana już w wielu artykułach w sieci ( m.in. tutaj ). Wszędzie niemalże wspomina się o ustawianiu typu partycji na fd, czyli Linux raid autodetect. Nazwa sugeruje, że ma to coś wspólnego z autowykrywaniem raidu. Otóż okazuje się, że miało w przeszłości. Parametry konfiguracyjny CONFIG_MD_AUTODETECT zniknął już jakiś czas temu z kernela i tym samym zniknęła też autodetekcja. Opisuje to ten artykuł. Jest tam geneza usunięcia autodetekcji i rozwiązanie problemu bootowania z raidu 1. Wiąże się to z odpowiednio wygenerowanym plikiem initramfs. Ja się złapałem na tym, że system nie wstawał poprawnie, gdyż liczyłem że odpowiednio poustawiane typy partycji zrobią swoje i podczas startu wszystkie macierze samoczynnie wystartują. Krótka analiza struktury initramfs i kilka minut na googlach przyniosły rozwiązanie. Musiałem powiadomić mdadm o istnieniu macierzy, a zatem po ich utworzeniu wywołać polecenie

mdadm --examine --scan >> /etc/mdadm.conf

Następnie należy wygenerować plik initramfs uwzględniający te zmiany – załączy on ten plik do swojego drzewa i podczas startu odpowiednio wywołany mdadm z poziomu initramfs wystartuje podane tam macierze.
W Ubuntu generujemy nowy initramfs dla obecnego kernela poleceniem

update-initramfs -u

Teraz już możemy cieszyć się mirrorowaną partycją /boot.

Proste statystyki wydruków z bazą sqlite

Potrzebowałem na szybko statystyk wydruków. Do tego skonstruowałem taki oto twór:

perl -ne 'print "$1 $2\n" if /(\d+\/[a-zA-z]+\/20\d{2}).*for job (\d+)\./' /var/log/cups/error_log|sort |uniq | awk '{print "insert into printouts values(\""$1"\","$2");"}'| sqlite3 printouts.db

Ten z pozoru niezgrabny jednolinijkowiec parsuje plik logów cupsa wyciągając z niego numer zadania i datę, a następnie wkłada to do prostej bazy sqlite`a.

Dzięki temu mogłem szybko wydobyć ilość wydruków na dzień. Przy niewielkiej modyfikacji można dołączyć inne pola i już grupować sobie w sqlu co tylko dusza zapragnie. Nie jest to może wyszukany przypadek – raczej ciekawostka. To samo można uzyskać również za pomocą uniq -c, ale perspektywy tego rozwiązania są o wiele większe.

Na koniec tylko polecenie tworzące trywialną strukturę bazy printouts.db:

sqlite3 printouts.db 'create table printouts(date text,job int)'

Ujarzmione logi apache

Na co dzień pracuję z aplikacją, która wyrzuca bardzo dużo “śmieci” do logów. Tym samym zapycha ona error log, który z nazwy powinien zawierać błędy, a nie informacje o niezainicjalizowanej zmiennej X. Postanowiłem ukrócić ten proceder i filtrować wychodzące z procesów apache`a komunikaty.

Wykorzystałem do tego perla, gdyż dość sprawnie radzi on sobie z obróbką tekstu i wyrażeniami regularnymi. Poniżej zawartość skryptu apache-logfilter.pl

#!/usr/bin/perl -w

use strict;

$|=1;   # use unbuffered output

my $logfile;

# check if logfile was passed as 1st argument
if ($ARGV[0])   {
$logfile=$ARGV[0];
}

# assign /dev/null as logfile unless it is already defined
$logfile="/dev/null" unless ($logfile);

# set umask
umask 0022;
my $loghandler=open(LOGFILE,'>>',$logfile);

# autoflush file handler
select((select(LOGFILE), $| = 1)[0]);

# inifinite loop over input from STDIN
while (<STDIN>) {

# omit unwanted lines matching the following patterns
next if (/^Use of uninitialized value/);
next if (/^"my" variable/);
next if (/^Subroutine \w+ redefined/);
next if (/^Variable ".*?" will not stay shared/);
next if (/^Odd number of elements in hash/);
next if (/^Argument ".*?" isn't numeric/);
next if (/^Useless use of .*? in void context/);
next if (/^substr outside of string at/);
next if (/^Unquoted string ".*?" may clash/);
next if (/^Scalar value @.*? better written as/);
next if (/^Parentheses missing around/);

# print to our logfile
print LOGFILE "$_";
}

Posiadając już taki skrypt należy przekazać w konfiguracji apache`a jego wywołanie. Odbywa się to za pomocą pipe`a przez który przekazywane są komunikaty do skrypty. W tym przypadku jako parametr podana jest ścieżka do właściwego pliku logu, do którego dopisywane są wiadomości (nie należy zapomnieć o właściwiej konfiguracji logrotate!).
Przykładowa część konfiguracji:


ErrorLog "|/usr/local/bin/apache-logfilter.pl /var/log/apache/error_log"

Ciekawą rzeczą jaką napotkałem tutaj był problem buforowanego wyjścia. Otóż do logu nie docierały żadne nowe wiadomości. Wielokrotnie sprawdzałem poprawność skryptu i za każdym razem działał on poprawnie zapuszczony z palca. Po krótkich poszukiwaniach znalazłem zmienną $|, której to niezerowe ustawienie powinno mój problem rozwiązać. A jednak nie rozwiązało. Dopiero wymuszenie tego na uchwycie otwartego pliku dało pożądane rezultaty. Odpowiada za to następujące wywołanie:


select((select(LOGFILE), $| = 1)[0]);

Teraz wszystko śmiga jak należy – czytelność logów zwiększyła się znacząco, a ich rozmiar zmniejszył się kilkukrotnie.

Na tropach procesu

Obecnie nie potrafię sobie wyobrazić porządnego debugowania/troubleshootingu bez strace`a. Dzięki niemu jestem w stanie śledzić wywołania systemowe i wychwytywać wszelkie błędy w oprogramowaniu w sytuacjach gdy logi już nie wystarczają. Dodatkowo zawsze jest to ciekawie obejrzeć działanie “od kuchni”.

Jak używać strace`a? Najłatwiej poprzedzić wywołanie programu poleceniem strace. Częściej jednak będziemy chcieli sprawdzić co robi dany proces uruchomiony już w tle. Wówczas należy wywołać:

strace -p PID_PROCESU

Jeśli program tworzy forki to również warto dodać parametr -f śledzący jego procesy potomne.

mkfs -t blog /root.eu

Kilka miesięcy temu narodził się w mej głowie pomysł utworzenia własnego bloga. Długo szukałem odpowiedniej domeny – niestety obecnie większość ciekawych nazw jest już powykupywana przez firmy liczące na zyski z odsprzedaży. Na szczęście tld eu pozostaje jeszcze niewyczerpaną studnią nazw, z której to wydobyłem właśnie slashroot.eu.

Blog ten będzie swoistego rodzaju notatnikiem, gdzie będę umieszczać ciekawe rozwiązania wymyślone lub też podpatrzone, wiążące się tematycznie z systemami operacyjnymi, sieciami, ciekawymi konfiguracjami, nieudokumentowanymi “ficzerami”, oraz wszystkim tym co będę uważał za istotne i czym chciałbym się podzielić z całą społecznością. Mam nadzieję, że będzie to pewnego rodzaju odwzajemniona przysługa jaką oddam za setki stron obecnych w internecie, z których to czerpałem i czerpię do tej pory wiedzę.

Jednocześnie postaram nie rozpisywać się za dużo na tematy osobiste i prywatne, gdyż nie leży to w mojej naturze. Dołożę natomiast wszelkich starań, aby strona ta zawierała ciekawą (chociażby dla googlujących) treść i aby jej aktualizacja odbywała się w miarę regularnie.