piątek, 12 października 2012

Zdalna rejestracja zdarzeń na stronach www - część 2

Mamy już gotową obsługę naszego trackera, jaką należy wykonać na śledzonej stronie. Teraz zajmiemy się skryptami, jakie będą znajdowały się na naszym serwerze. Będą one odpowiedzialne za właściwą część związaną z rejestracją zdarzeń na zdalnym serwisie.

Na początek skrypt tracker.js
var bustersT = {
    _key : '',
    init : function(key) { 
        this._key = key;
    },
    _trackEvent : function(name, value) {
        var img = document.createElement('IMG');
        img.src = 'http://tracker.pl/'+value+'/'+name+'.png?'+(Math.random());
    },
    eOrder : function(options) {
        options.key = this._key;
        var opt64 = _base64(JSON.stringify(options));
        
        this._trackEvent('eOrder', opt64);
    }
}

var _phpbustersTtmp = [];

if((typeof window._phpbustersT) == 'object' && typeof window._phpbustersT.length != 'undefined' && window._phpbustersT.length > 0)
{
    _phpbustersTtmp = window._phpbustersT;
}

window._phpbustersT = {
    push : function(value)
    {
        if(value[0] == 'key')
        {
            bustersT.init(value[1]);
        }
        else
        {
            bustersT[value[0]](value[1]);
        }
    }
}

for(var i=0; i<_phpbustersTtmp.length; i++)
{
    window._phpbustersT.push(_phpbustersTtmp[i]);
}

W skrypcie wykorzystana jest metoda _base64. Takiej metody nie ma w javascript. Należy użyć zewnętrznej biblioteki do kodowania base64 lub napisać własną funkcję (to bardzo proste - postaram się opisać to w jednym z kolejnych postów).

Skrypt wykorzystuje kilka "sprytnych" możliwości JS.
Po pierwsze, można go załadować w dowolnym momencie, dzięki "symulacji" metody "push" obiektu Array.
Po drugie, skrypt dynamicznie tworzy nam element obrazka (tag img). Dzięki temu możemy przekazać dane do skryptu, który znajduje się w innej domenie niż śledzona strona (odwołanie AJAX zostało by zablokowane).
Po trzecie, dzięki temu, że skrypt również dynamicznie osadzamy w kodzie strony, nie będzie on powodował spowolnienia lub "zawieszenia" się śledzonego serwisu.

W kolejnym poście przedstawię skrypt php, który odbierze i zapisze dane z tracker.js.

poniedziałek, 1 października 2012

Zdalna rejestracja zdarzeń na stronach www - część 1

Naszła mnie ostatnio ochota na stworzenie narzędzia pozwalającego śledzić określone zdarzenia na stronach. Całość ma działać na zasadach wtyczki - podobnie jak jest to rozwiązane w Google Analytics.

Podstawowy cel to maksymalna prostota części jaka ma zostać umieszczona na śledzonej stronie. Chodzi o ty by kod był prosty i czytelny. Jeśli zbyt wiele będziemy wymagać od właścicieli strony, raczej nie zgodzą się na ingerencję.

Inny ważny aspekt to możliwie jak największe bezpieczeństwo. Nie może stać się tak, że "pad" naszej maszyny spowoduje problemy w działaniu śledzonej witryny.

Oto pomysł jaki przyszedł mi do głowy.

Na początek wstawiamy kod inicjujący rejestrację zdarzeń. Możemy umieścić go w sekcji head śledzonej strony.
<script type="text/javascript">
   window._phpbustersT = window._phpbustersT || [];
   _phpbustersT.push(['key',  'IDENTYFIKATOR_ŚLEDZONEJ_STRONY' ] );
</script>

Dla jasności: powyższy kod utworzy nam tablicę globalną (jeśli jeszcze nie istniała) w polu "_phpbustersT" obiektu window. Tę tablicę będziemy nazywać "śladem", ponieważ to na niej będą się odciskać działania naszego użytkownika.

Teraz musimy określić sobie zdarzenia jakie chcemy logować, a następnie podpiąć do nich odpowiedni kod. Dla ułatwienia użyjemy jQuery.
<script type="text/javascript">
$('#orderButton').bind('click', function()
{
   window._phpbustersT = window._phpbustersT || [];
   _phpbustersT.push(['eOrder', { orderid : 12345678 } ] );
});
</script>


Teraz pozostaje nam już tylko dodanie skryptu js, który poinformuje nas o zdarzeniach na śledzonej stronie.
<script type="text/javascript">
(function() {
    var bust = document.createElement('script'); 
        bust.type = 'text/javascript'; 
        bust.async = true;
        bust.src = ('https:' == document.location.protocol ? 'https://' : 'http://')+
                    'tracker.phpbusters.eu/tracker.js?'+(Math.random());
    var s = document.getElementsByTagName('script')[0]; 
        s.parentNode.insertBefore(oi, s);
})();
</script>

W ostatnim skrypcie istotnych jest kilka elementów.

  1. może zostać umieszczony w dowolnym miejscu w kodzie strony (oczywiście z zachowaniem poprawności HTML ;])
  2. wywołuje się asynchronicznie dzięki czemu nie zawiesi nam strony, jeśli podczas jego pobierania wystąpią błędy lub opóźnienia.
  3. jeśli skrypt nie zostanie pobrany lub będzie zawierał błędy składniowe - nie będzie to miało żadnych konsekwencji dla śledzonej strony.
Treść skryptu trackera oraz skrypt logujący przedstawię w kolejnym poście.

piątek, 28 września 2012

Autorskie frameworki do PHP - część 3. Wydajność i bezpieczeństwo



  1. Autorskie frameworki do PHP - część 1. Wstęp
  2. Autorskie frameworki do PHP - część 2. Użytkownicy
  3. Autorskie frameworki do PHP - część 3. Wydajność i bezpieczeństwo

User to nie wszystko..... Pewnie, że nie!

Nasz system musi spełniać wymagania z innych zakresów niż UX. Musi być wydajny i bezpieczny. Zagrażają mu ataki zarówno ze strony hakerów, jak i zwykłych użytkowników uzbrojonych w ilość maszyn i jednoczesnych połączeń. Pierwsza kwestia często jest lekceważona. Przecież hakerzy są tylko na filmach i w książkach Stiega Larssona. Nie jest to jednak prawda. Fakt, "włamania" na strony sklepów internetowych i zmiany cen wszystkich sprzedawanych produktów na 1PLN, to zwykle dzieło niezadowolonego pracownika zwolnionego 3 dni wcześniej. To niewiele ma wspólnego z hakerami. Co innego jest w przypadku stron dużych instytucji takich jak uczelnia. Tu częściej możemy mieć do czynienia z prawdziwymi atakami, gdyż włamania do takich systemów są zwykle powodem do dumy i dają parę punktów do szacunku w "środowisku". Przy projektach tego typu i takiej skali wiele pracy należy włożyć w bezpieczeństwo.  Dodatkowo pamiętajmy, że budujemy sporą bazę danych osobowych, zatem podlegamy kontroli GIODO!

Wydajność jest równie ważna. Dla kandydata na wymarzony kierunek na wymarzonej uczelni dzień publikacji wyników rekrutacji to najważniejszy dzień w życiu (przynajmniej tak mu się wówczas wydaje). Nic więc dziwnego, że jeśli obiecano mu wyniki rekrutacji 5 lipca o 12:00, to on i 100 000 jego kolegów wejdzie na stronę już o 11:55, by sprawdzić czy się dostał. Potem odświeży tę stronę jeszcze 100 razy by być pewnym, że nie śni, lub by pochwalić się babci. Taki "pik" potrafi zaskoczyć zarówno programistów i adminów, jak i nawet same serwery (nawet te od dużej mocy).

Niestety w przypadku każdego projektu musimy brać pod uwagę jego koszty. Liczą się licencje i opłaty za wsparci czy szkolenia. Lwią część zawsze stanowi koszt programistów, testerów i obsługi systemu. Musimy również zakładać ewentualne koszty związane z wystąpieniem błędów, które nie zostaną wykryte podczas testów, a mogą narazić nas na dodatkowe koszty takie jak odszkodowania czy koszty sądowe.

Mamy już podstawowy zasób wiedzy, potrzebny do podjęcie decyzji o wyborze frameworku, z pomocą którego będziemy realizować nasz projekt. Czas podjęć decyzję...

Rozważając wszystkie aspekty przedstawione przeze mnie wcześniej decyduję się na niewątpliwie droższe i bardziej pracochłonne rozwiązanie (przynajmniej w początkowym okresie), czyli na autorski framework. Projekt jaki będziemy tworzyć musi być bardzo elastyczny. Musi dać się dostosować do różnych grup użytkowników jak i umożliwiać szybkie dostosowanie do zmian prawa i przepisów uczelni. Technologie muszą nam stawiać jak najmniejszy opór i musimy posiadać odpowiednią kadrę fachowców. Zacznijmy od warstwy najniższej, czyli wybierzmy system operacyjny na jakim oprzemy nasz projekt. Ze względów politycznych warto by zdecydować się na platformę opensource. Jest w dobrym tonie jeśli uczelnie i urzędy promują właśnie takie rozwiązania. Dodając do tego wysoce wyspecjalizowaną kadrę fachowców od systemu linux wybór wydaje się oczywisty. Wybrana dystrybucja nie wydaje się,  istotna w kontekście niniejszego artykułu. Kolejna kwestia to baza danych. MSSQL możemy skreślić od razu, z racji wybranego przez nas systemu jak i z powodów politycznych (podobnych jak w przypadku OS). Z powodu kosztów jak i licencji musimy również zrezygnować z produktu firmy Oracle. Pomimo, iż przy gabarytach system jest to wybór dość oczywisty. Na placu boju pozostały jeszcze dwa systemu bazodanowe: MySQL i PostgreSQL. Inne systemu nie są rozważane z powodu braku kadry potrafiącej je obsługiwać. W tym przypadku wybór jest chyba oczywisty. Moim zdaniem Postgres znacznie lepiej nadaje się do użytku w dużych systemach. Mając już dwa istotne elementy naszej platformy. Przychodzi pora na język programowania oraz serwer www.  Mamy zatem alternatywę Java i PHP. Java jest trendy, ale jednocześnie jest dość ciężka i wiele wymaga zarówno od programistów jak i od serwerów. Wiem, wiem! Znam statystyki i testy porównawcze wydajność Javy i pehapa. Tylko jestem praktykiem, a w praktyce PHP ma mniejsze wymagania. I kropka. 

Mamy zatem wybrany język programowania. Łatwy, niezbyt wydajny, ale da się jakość żyć. Do tego Apache jako jedyny słuszny serwer (ten pogląd jeszcze skorygujemy w przyszłości). Mamy chyba komplet. Teraz czas na framework. Mamy Symfony, Zend'a czy CakePHP, jak i wiele innych. Są darmowe (lub nie bardzo drogie). Ale stawiają nam pewne wymagania i ograniczenia. Własne rozwiązanie możemy bardzo mocna dostosować do wybranej przez nas platformy i silnika bazy danych jak i do specyfiki projektu. Dodatkowo możemy już na etapie projektowanie zaplanować szkolenia i dokumentacje co ułatwi nam rekrutacje programistów. Wystarczy, że znajdziemy dobrego programistę PHP i poświęcimy na jego szkolenie kilka dni. A powinien dobrze sobie radzić w naszym projekcie. Koszt własnego rozwiązania będzie oczywiście znacznie wyższy niż zakup licencji czy użycie produktów darmowych. Jest to jednak koszt o charakterze inwestycji. Taka instytucja jak uczelnie może z czasem sprzedać cały projekt systemu jak i sam framework. Co pozwoli na obniżenie kosztów budowy frameworku, a niekiedy może nawet okazać się dochodowe.

Znamy już powody wyboru własnych rozwiązań dla PHP. Poznaliśmy również zasady i argumenty brane pod uwagę podczas podejmowania takiej decyzji. Rozumiemy też cześć wymagań jakie nasze rozwiązanie ma spełniać i wiemy jakie zadania będą przed nim stawiane. W kolejnych artykułach postaram się przedstawić proces powstawania takiego właśnie frameworku. Jako przykład posłuży mi niekomercyjny framework zwany: silnikiem, którego jestem współautorem oraz kilka innych autorskich rozwiązań z jakimi miałem okazje pracować. Postaram się pokazać pułapki w jakie można wpaść, problemy i ich rozwiązania.

Mam nadzieje, że uda mi się pójść również o krok dalej i pokazać jak można wykorzystać darmowe rozwiązania takie jak Postgres, PHP czy linux by budować szybkie, bezpieczne i łatwe w rozbudowie systemy informatyczne na dużą skalę.

Autorskie frameworki do PHP - część 2. Użytkownicy





  1. Autorskie frameworki do PHP - część 1. Wstęp
  2. Autorskie frameworki do PHP - część 2. Użytkownicy
  3. Autorskie frameworki do PHP - część 3. Wydajność i bezpieczeństwo



Rozważmy teraz kwestie użytkowników....
Projektując każdy system informatyczny największą wagę należ poświęcić właśnie tej kwestii. Pamiętajmy, że to właśnie dla userów tworzymy nasze tkownidzieło. Zwykle systemy elektroniczne mają pewne grupy użytkowników. Grupy, te charakteryzują się zwykle pewną pulą cech wspólnych. Zazwyczaj będą to uprawnienia lub cele w jakim używają naszego system. Nasz przykładowy projekt nie różnie się w tej kwestii od innych. Już po wstępnej analizie możemy wyodrębnić trzy podstawowe grupy użytkowników. Spróbujmy je zatem nazwać i scharakteryzować.


  1. Kandydaci na studia. Grupa potencjalnie najbardziej oczywista. Ludzie młodzi i inteligentni mający duże doświadczenie w użytkowaniu komputerów - Dzieci Neo - czyli superuserzy... ale czy na pewno? :D Okazuje się, że kandydat na studia nie zawsze daje się tak łatwo "zaszufladkować". Zwróćmy uwagę, że na studia idą osoby w różnym wieku. Oczywiście przytłaczającą większość stanowią tegoroczni maturzyści, ale przy projektowaniu systemu znacznie większą wagę powinniśmy zwrócić na przypadki, rzadkie i bardzo rzadkie, niż na te pospolite. Dlaczego? To proste, osoby ze schematu to znany nam przypadek i raczej nie zapomnimy o jego potrzebach. Osoby odstające od schematu to przypadki trudne, najmniej nam znane i mało przez nas rozumiane. Łatwo więc będzie nam pomylić się czy zapomnieć o pewnych drobiazgach - w artykułach z tego cyklu wrócę jeszcze do tej kwestii - więc zapamiętajmy ją sobie. Wracając do naszych kandydatów. Tworzymy system dla ludzi posługujących się biegle komputerami i dla osób, które nie wiedzą w jaki sposób zmusić komputer do wyświetlenia wielkiej litery bądź litery "ś", że o "ź" nie wspomnę. Będą to ludzie w wieku 18 jak i 55 lat. Mieszkańcy miast (którzy często nie znają nazwy gminy w jakiej mieszkają) jak i mieszkańcy wsi (w których nie mamy nazw ulic, czy numerów mieszkań). Będą to osoby nieprzeciętnie inteligentne jak i takie, które ukończyły prywatną szkołę jedynie dlatego, że "ich tatuś tę szkołę kupił". Generalnie pełne spektrum naszego społeczeństwa :)
  2. Pracownicy uczelni obsługujący system. To również bardzo ciekawa i zaskakująca grupa. Nazwijmy sobie tę grupę dla ułatwienia "wsparciem". Nasi pracownicy to powiedzmy: 3-4 pracownice jednego z działów naszej uczelni. Powiedzmy że, są to osoby w wieku lat 45+. Powiedzmy że, nie potrafią się posługiwać komputerem i nie są zbyt chętne do nauki nowych rzeczy czy podejmowania zawodowych wyzwań - typowi urzędnicy wychowani w poprzednim systemie. Resztę wsparcia stanowią informatycy: bazodanowcy, programiści i administratorzy systemu. Większość z nich jest przekonana o swojej nieomylności oraz wyższości nad resztą społeczeństw, a ich cenny czasz jest marnotrawiony przez błahe problemy maluczkich. Co bardzo istotne ich czas faktycznie jest cenny, gdyż takie osoby często zarabiają więcej niż urzędnicy. Ostatnia podgrupa to "pracownicy sezonowi". Osoby przychodzące do pracy wyłącznie w okresie największej ilości pracy do wykonania mające pomagać etatowym pracownikom wsparcia. Jak każdy zbieracz ogórków, nie mają odpowiedniego wykształcenia, doświadczenia i kwalifikacji. Nie możemy im do końca ufać, gdyż zwykle nie możemy wyciągać konsekwencji za ich czyny. Nie możemy również od nich wymagać zbyt wiele, bo przyszli tu tylko na chwilkę i za moment lecą dalej.
  3. Komisje rekrutacyjne. Grupa użytkowników składające się wyłącznie z naukowo-dydaktycznych pracowników uczelni. Jednak do samej obsługo systemu oddelegowywane są osoby o najniższych tytułach naukowych/zawodowych o najkrótszym stażu na uczelni. Zwykle jest to doktorant nie mający dość silnej pozycji jak ich dość odwagi by sprzeciwić się swoim przełożonym profesorom będącym przewodniczącymi komisji rekrutacyjnych. Te osoby jednak mają dość odwagi i przekonania o swej silnej pozycji by wymagać "niemożliwego" od pracowników wsparcia :D.
Z grubsza to tyle co do userów naszej aplikacji. Ale pamiętajmy, że w skład projektu wchodzi również wybór frameworku. Zatem mamy potencjalnie jeszcze jedną grupę userów. Programistów, dbających o rozwój i utrzymanie naszej aplikacji. Tego typu projekty zwykle są rozwijane w sposób ciągły. Stale dokładane są nowe moduły i udoskonalane stare. Projekt musi być dostosowywanych do nowych przepisów oraz zasad rekrutacji. Np. ministerstwo wprowadza "Nową maturę" co zupełnie zmienin dotychczasowe podejście do pozyskiwania informacji o wynikach naszych kandydatów. Grupa ta powinna być zatem potraktowana w sposób szczególny. Istotne jest to z jaką łatwością będzie można wprowadzać zmiany do systemu lub lokalizować błędy. Jak również, to jak łatwo rekrutować nowych programistów, posiadających odpowiednią wiedzę i kwalifikacje. 

User to nie wszystko.....

czwartek, 22 marca 2012

Prędkość dysków SAS w próżni

Udało nam się dziś udowodnić, że żadna kolej, samochód czy motor nie mają szans z serwerowymi dyskami twardymi firmy IBM typu: SAS 15K rpm.

Dla chętnych możecie sprawdzić nasze obliczenia, ale na dysku z Łodzi do Warszawy dojedziecie w ~30min.

A oto jak do tego doszliśmy i do czego jeszcze można wykorzystać SQL:

select (1.75*2.54*2*3.14*250)*3600/100/1000

poniedziałek, 8 sierpnia 2011

Zmiana rozmiaru partycji LVM (/var) poczas pracy systemu

Przyjmijmy, że mamy serwer, którego z różnych względów nie powinniśmy wyłączać. Nawet na kilka minut. Jednocześnie na serwerze kończy nam się miejsce na ważnej partycji (w tym przypadku jest to home). Mamy jednak trochę wolnego miejsca na innych partycjach. No i mamy LVM-a.
Rozwiązanie jest proste: "przesuniemy" trochę wolnej przestrzeni z innej partycji :).

Na początek musimy zorganizować taką wolną przestrzeń.

serwer:/# df -h

Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vgraid1-root 4.0G 423M 3.4G 12% /
tmpfs 4.4G 0 4.4G 0% /lib/init/rw
udev 10M 56K 10M 1% /dev
tmpfs 4.4G 0 4.4G 0% /dev/shm
/dev/sda1 183M 19M 155M 11% /boot
/dev/mapper/vgraid1-home 16G 2.6G 13G 18% /home
/dev/mapper/vgraid1-usr 16G 624M 15G 5% /usr
/dev/mapper/vgraid1-var 15.0G 235M 14.6G 2% /var

Jak widać na /var mamy sporo wolnego marnującego się miejsca i je właśnie wykorzystamy. Modyfikować możemy wyłącznie partycje, które nie są zamontowane. Odmontujemy zatem /var !

serwer:/# umount /var

umount: /var: device is busy
umount: /var: device is busy

Nie da się :( - mogliśmy się tego spodziewać - partycja jest używana. Musimy zadbać by nie była.

serwer:/# lsof |grep /var

acpid 12208 root 1w REG 254,4 159 626 /var/log/acpid
acpid 12208 root 2w REG 254,4 159 626 /var/log/acpid
cron 12224 root cwd DIR 254,4 4096 676 /var/spool/cron
cron 12224 root 3u REG 254,4 6 701 /var/run/crond.pid
syslogd 12241 root 1w REG 254,4 126215 194 /var/log/auth.log
syslogd 12241 root 2w REG 254,4 30750 160 /var/log/syslog
syslogd 12241 root 3w REG 254,4 4590 190 /var/log/daemon.log
syslogd 12241 root 4w REG 254,4 0 195 /var/log/kern.log
syslogd 12241 root 5w REG 254,4 0 1217 /var/log/lpr.log
syslogd 12241 root 6w REG 254,4 0 1218 /var/log/mail.log
syslogd 12241 root 7w REG 254,4 0 189 /var/log/user.log
syslogd 12241 root 8w REG 254,4 0 1220 /var/log/uucp.log
syslogd 12241 root 9w REG 254,4 0 1221 /var/log/mail.info
syslogd 12241 root 10w REG 254,4 0 1222 /var/log/mail.warn
syslogd 12241 root 11w REG 254,4 0 1223 /var/log/mail.err
syslogd 12241 root 12w REG 254,4 0 1224 /var/log/news/news.crit
syslogd 12241 root 13w REG 254,4 0 1225 /var/log/news/news.err
syslogd 12241 root 14w REG 54,4 0 1226 /var/log/news/news.notice
syslogd 12241 root 15w REG 254,4 0 405 /var/log/debug
syslogd 12241 root 16w REG 254,4 3525 191 /var/log/messages
ntpd 12255 ntpd cwd DIR 254,4 4096 713 /var/run/openntpd
ntpd 12255 ntpd rtd DIR 254,4 4096 713 /var/run/openntpd

Ok! żaden z programów nie wydaje się skrajnie ważny. System bez nich przez chwilę sobie poradzi. Zatem do dzieła. Wyłączamy usługi używające partycję /var.

serwer:/# lsof |grep /var

serwer:/# /etc/init.d/acpid stop
serwer:/# /etc/init.d/cron stop
serwer:/# /etc/init.d/sysklogd stop
serwer:/# /etc/init.d/openntpd stop

sprawdzamy czy jeszcze coś nie zostało

serwer:/# lsof |grep /var |wc -l

0

To jest TEN MOMENT kiedy należy zrobić backup danych z partycji, którą zamierzamy modyfikować. Ja zrobiłem to tak


serwer:/# tar cvvf var_backup.tar /var



Ok. Teraz możemy odmontować /var

serwer:/# umount /var


Sukces!

Teraz powinniśmy sprawdzić poprawność partycji:

serwer:/# e2fsck -f /dev/mapper/vgraid1-var

e2fsck 1.40-WIP (14-Nov-2006)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/mapper/vgraid1-var: 1419/1831424 files (4.2% non-contiguous), 119616/3670016 blocks

Teraz zmienimy rozmiar partycji /dev/mapper/vgraid1-var. Najpierw musimy zmienić jej rozmiar na mniejszy niż jej rozmiar docelowy. W naszym przypadku rozmiar docelowy to 5G zatem zmniejszymy sobie rozmiar systemu plików do 3G.

serwer:/# resize2fs -p /dev/mapper/vgraid1-var 3G

resize2fs 1.40-WIP (14-Nov-2006)
Resizing the filesystem on /dev/mapper/vgraid1-var to 786432 (4k) blocks.
Begin pass 2 (max = 4448)
Relocating blocks XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 112)
Scanning inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 4 (max = 106)
Updating inode references XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/mapper/vgraid1-var is now 786432 blocks long.

teraz zmniejszymy sobie partycję LVM:

serwer:/# lvreduce --size 5G /dev/vgraid1/var

WARNING: Reducing active logical volume to 5.00 GB
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce var? [y/n]: y
Reducing logical volume var to 5.00 GB
Logical volume var successfully resized

a następnie ponownie uruchomimy resize2fs, ale teraz bez podawania rozmiaru systemu plików. Wówczas zostanie on ustawiony na maksymalny możliwy na danym urządzeniu
serwer:/# resize2fs -p /dev/mapper/vgraid1-var

resize2fs 1.40-WIP (14-Nov-2006)
Resizing the filesystem on /dev/mapper/vgraid1-var to 1310720 (4k) blocks.
Begin pass 1 (max = 16)
Extending the inode table XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/mapper/vgraid1-var is now 1310720 blocks long.

I tyle. Pozostaje nam jeszcze ponownie zamontować partycję i uruchomić wcześniej zatrzymane usługi

serwer:/# mount /var

serwer:/# /etc/init.d/acpid start
serwer:/# /etc/init.d/cron start
serwer:/# /etc/init.d/sysklogd start
serwer:/# /etc/init.d/openntpd start

dzięki tej operacji mamy 10G nieprzydzielone do żadnej partycji. Wykonaliśmy już 50% zadania.
Teraz czas na zwiększenie partycji /home.

Podobnie jak poprzednio musimy zrobić backup a następnie odmontować partycję, którą będziemy modyfikować.

serwer:/# tar cvvf home.tar /home

serwer:/# umount /home

Teraz zmieniamy rozmiar partycji przydzielając jej zaoszczędzone wcześniej 10G

serwer:/# lvextend -L+9G /dev/vgraid1/home

Wykonujemy sprawdzenie systemu plików oraz resize:
serwer:/# e2fsck -f /dev/mapper/vgraid1-home

e2fsck 1.40-WIP (14-Nov-2006)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/mapper/vgraid1-home: 272/2097152 files (26.8% non-contiguous), 226212/4194304 blocks

oraz resize:
serwer:/# resize2fs /dev/mapper/vgraid1-home

I ponownie montujemy partycję:

serwer:/# mount /home

I tyle! Cieszymy się nowo uzyskanym wolnym miejscem na partycji home.