niedziela, 23 listopada 2014

Wyliczanie mediany w bashu :).

Ostatnio miałem okazję napisać skrypt do wyliczania mediany w bashu, więc postanowiłem się nim podzielić.
Skrypt jest dość ciekawy, ponieważ korzysta z różnych narzędzi dostępnych w systemie operacyjnym Linux.

Zawartość skryptu:

#!/bin/bash
a=`cat $1 | wc -l `
echo "Lista składa się się z $a elementów"

if [ `expr $a % 2` -ne 0 ]
then
echo "$a jest nieparzystą liczbą elementów"
b=`expr $a / 2 + 1` ### Zmienna zawierająca środkową wartość
echo "Element, którego wartości poszukuję to $b "
echo "Jego wartość to `cat $1 | sort -n | sed -n "$b"p`"

else


echo "$a jest parzystą liczbą elementów"
### Ustawienie zmiennej lista elementów podzielona na dwa oraz lista elementów podzielona na dwa i plus jeden.
c=`expr $a / 2`
d=`expr $a / 2 + 1`
echo "Poszukiwane są wartości elemntu $c oraz $d"
### Ustawienie wartości dla zmiennych c oraz d
cc=`cat $1 | sort -n | sed -n "$c"p`
dd=`cat $1 | sort -n | sed -n "$d"p`
ee=`expr $cc + $dd`

echo "Które mają nastepujące wartości $cc oraz $dd"
echo "Wynik dla parzystej ilości liczb wynosi:"
echo "`echo $ee 2 | awk '{print $1/$2}'`"

fi


Wzory na wyliczenie mediany znalazłem na stronie http://www.matmana6.pl/tablice_matematyczne/liceum/statystyka/44-mediana_wariancja_i_odchylenie_standardowe .
Są dostępne dwie jego wersje pierwszy dla nieparzystej ilości analizowanych liczb, drugi dla parzystej liczby analizowanych liczb.
Dla nieparzystej ilości liczb medianą jest środkowa liczba ze wzoru.
Dla parzystej ilości liczb medianą jest średnia wyciągnięta z dwóch liczb najbliżej środka.


Rozbicie skryptu na czynniki pierwsze :):
a=`cat $1 | wc -l ` ### Tworzymy zmienną "a" i sprawdzamy ile ma elementów (przydatne do późniejszego sprawdzenia czy mamy do czynienia z parzystą czy też nieparzystą ilością liczb).

if [ `expr $a % 2` -ne 0 ] ### Sprawdzamy czy ilość elementów jest nieparzysta "% 2" oznacza że dzielimy przez dwa i jest zwracana reszta z dzielenia, jeżeli wynik jest równy 0 to wówczas mamy do czynienia z liczbą parzystą, jeśli nie to jest to liczba nieparzysta (stosujemy pierwszy wzór).

b=`expr $a / 2 + 1` ### Tworzymy zmienną b, dzielimy ilość elementów na dwa (expr auto-magicznie zaokrągli wynik w dół) i dodajemy jeden aby znać numer elementu ze środka przedziału.

echo "Jego wartość to `cat $1 | sort -n | sed -n "$b"p`" ### Rozpoczynam działania na pliku który podałem podczas uruchomienia skryptu (przykładowe wywołanie skryptu "./skrypt.sh lista.txt"), sortuje po numerach liczby umieszczone w pliku lista.txt i wyświetlam za pomocą sed zawartość środkowego wiersza z pliku. Ta dam i mamy medianę :).

c=`expr $a / 2` ### Tworze dwie zmienne odpowiadające elementom listy najbliżej środka ( np. dla listy 1 2 3 4, będzie to 2 i 3)
d=`expr $a / 2 + 1`


cc=`cat $1 | sort -n | sed -n "$c"p` ### Przypisuję wartości dla elementów najbliżej środka przedziału
dd=`cat $1 | sort -n | sed -n "$d"p`

ee=`expr $cc + $dd` ### Dodaję wartości obu zmiennych


echo "`echo $ee 2 | awk '{print $1/$2}'`" ### Ten fragment jest trochę przekombinowany dlatego, że expr nie chciał podawać wyników z dokładnością do dwóch miejsc po przecinku. Przekazałem więc dwa argumenty do programu awk i je przez siebie podzieliłem.

Zawartość przykładowych plików na których testowałem skrypt:

cat lista.txt
1
7
3
5
8

cat lista2.txt
1
3
5
6
10
8

Wynik wykonania skryptu na obu listach:
pawel@debian:~/mediana$ ./skrypt.sh lista.txt
Lista składa się się z 5 elementów
5 jest nieparzystą liczbą elementów
Element, którego wartości poszukuję to 3
Jego wartość to 5

pawel@debian:~/mediana$ ./skrypt.sh lista2.txt
Lista składa się się z 6 elementów
6 jest parzystą liczbą elementów
Poszukiwane są wartości elemntu 3 oraz 4
Które mają nastepujące wartości 5 oraz 6
Wynik dla parzystej ilości liczb wynosi:
5.5

Zdaję sobie sprawę z tego, że wykonywanie obliczeń statystycznych w bashu trochę mija się z celem ale i tak postanowiłem ten skrypt opublikować.
Może komuś przyda się, któraś z metod np. wyświetlanie wiersza o specyficznym numerze za pomocą sed.







sobota, 15 listopada 2014

Pobieranie całej strony do czytania offline

Celem jest pobranie całej strony, następnie konwertowanie plików html do plików txt, usunięcie wszystkich pustych wierszy i zapisanie w jednym wielkim pliku.

Całość rozbiła się o dwie pętle plus pobranie całe zawartości:
wget -r http://nazwa_strony.pl/
for i in $(find ./* -name index.html*); do html2text -utf8 $i > $i.txt ; done
for i in $(find ./* -name index.html.txt*); do cat $i | grep -v ^$ >> plik.txt ;done

Wget pobiera rekurencyjnie całą stronę.
Pierwsza pętla for wyszukuje wszystkie pliki index.html* i dla każdego z nich przeprowadza konwersję na plik txt (ustawiam też kodowanie utf-8).
Druga pętla wyszukuje wszystkie przerobione pliki txt, usuwa z nich puste wiersze za pomocą grep -v ^$ i przekierowuje do pliku.

Pozostaje jeszcze w notatniku zrobić zamień z powtarzających się elementów strony np. menu na nic zapisać zmiany i strona do czytania offline gotowa.

Niektóre osoby wolałby prawdopodobnie podzielić sobie zawartość strony na różne pliki, ale w tym przypadku zleceniodawca miał ściśle określone preferencje :).

wtorek, 1 kwietnia 2014

Automatyczne wyłączenie komputera po zakończeniu pobierania transmission

Skrypt ma na celu automatyczne wyłączenie programu transmission po zakończeniu pobierania torrentów.
Jeżeli skrypt zostanie wywołany z poziomu root'a wówczas nastąpi wyłączenie komputera.

Przygotowanie transmission do pracy ze skryptem:
- ustawienie rozszerzenia pliku ".part" dla nieskończonych pobierań (przejść na edycja >> preferencje >> zakładka torrenty >> sekcja Pobieranie i zaznaczyć check box obok "Dodawanie '.part' do nazw nieukończonych plików"),
- zapisywanie plików w (ta sama lokalizacja co powyżej, ja ustawiłem wspólny katalog dla ukończonych oraz nieukończonych pobierań),
- można ustawić wywołanie skryptu po ukończeniu torrenta (ta sama lokalizacja co powyżej), ja z tej opcji nie korzystam, ponieważ gdybym chciał aby wyłączyć komputer po zakończeniu pobierania za pomocą tej opcji, transmission musiało by zostać uruchomione z poziomu root'a (potencjalne zagrożenie bezpieczeństwa).


Po stronie systemu operacyjnego:
- uruchamianie skryptu z poziomu zwykłego użytkownika za pomocą crontaba (nastąpi wyłączenie transmission bez wyłączenia komputera)
- uruchamianie skryptu z poziomu root'a za pomocą crontaba (nastąpi wyłączenie transmission oraz wyłączenie komputera)

Dodawanie skryptu do crontaba (zwykły użytkownik):
- w konsoli crontab -e i dodanie wiersza
*/2 * * * * /bin/bash /home/pawel/torrent_killer.sh

W powyższym przykładzie skrypt będzie uruchamiany co drugą minutę (przy tej opcji bardziej opłacalne jest ustawienie w transmission automatycznego uruchamiania skryptu po zakończeniu pobierania, ponieważ nastąpi tylko wyłączenie transmission bez wyłączenia komputera).

Dodawanie skryptu do crontaba (root):
- w konsoli crontab -e i dodanie wiersza
*/2 * * * * /bin/bash /home/root/torrent_killer.sh

Przy tej opcji po zakończeniu pobierania nastąpi wyłączenie komputera.

Zawartość skryptu:
#!/bin/bash

# Variables

Download_Folder="/home/pawel/Pobrane/torrenty/"
Killer=`ps aux | grep transmission | grep -v grep | awk '{print $2}'`

# Sprawdzenie czy w katalogu pobierań znajdują się niezakończone pobierania

# Instrukcja warunkowa sprawdzająca czy wszystkie pobierania się zakończyły i wyłączająca klienta transsmision

if [ ! -z `pidof transmission` ] && [ ! -z `find $Download_Folder -name \*.part -type f | head -n1 |awk '{print $1}'` ]
then echo "Znaleziono pliki"
else
if [ ! -z `pidof transmission` ]
then echo "Nie znaleziono plików *.part, ubijam transsmision" && kill -9 $Killer && halt -p

else
echo "Transmission nie jest uruchomiony"
fi
fi


Komentarz do skryptu:
Download_Folder - musi być ustawiony taki sam jak w programie transmission, żeby można było odnaleźć pliki z niedokończonymi pobieraniami
Killer - znalezienie id procesu programu transmission w celu późniejszego jego wykorzystania do zamknięcia transmission
pierwszy if - sprawdzenie czy program transsimison działa jeżeli tak to sprawdzenie czy w Download_Folder znajdują się pliki *.part, (potrzebne były head i awk aby wyświetlić tylko jedną wartość, w przeciwnym wypadku test otrzymywałby zbyt wiele argumentów). Jeżeli zostały znalezione pliki part jest wyświetlany komunikat "Znaleziono pliki" i kończone jest wykonywane skryptu. Konieczne jest sprawdzenie działania programu transmission w przeciwnym wypadku przy dodaniu skryptu do crona z poziomu root'a komputer by się cały czas wyłączał.
drugi if - sprawdzenie czy program transmission działa, jeśli tak to jest wyświetlany komunikat "Nie znaleziono plików *.part, ubijam transsmision" oraz wykonywane jest zamknięcie programu transmission (zwykły użytkownik) lub zamkniecie programu i wyłączenie komputera (root).
ostatni else - jeżeli program transmission nie jest uruchomiony następuje wyświetlenie komunikatu "Transmission nie jest uruchomiony" i kończone jest działanie skryptu


Uwagi:
- skrypt jest trochę rozbudowany (overkill :) ) jak na taką prostą czynność, można to zrobić inaczej ale do moich potrzeb nadaje się idealnie,
- na moim komputerze miałem wcześniej włączone uruchamianie skryptu z poziomu zwykłego użytkownika co minutę ale czasami następowało wyłączenie transmission zanim zostało rozpoczęte pobieranie, więc częstotliwość została zmieniona do dwóch minut
- jeżeli ktoś będzie chciał korzystać ze skryptu do wyłączania komputera po zakończeniu pobierania oprócz uruchamiania crona z konta użytkownika root należy rozważyć uruchamianie w większych odstępach czasu np. 5 lub 10 minut. Nie powinno się mieć przy tym ustawieniu włączonego automatycznego uruchamiania transmission po włączeniu komputera - przy braku pobierania torrentów następowałoby automatyczne wyłączanie komputera.




sobota, 22 lutego 2014

Zmniejszanie partycji ext4

Tak samo jak w poprzednim poście, jeżeli mamy fizyczny dostęp do serwera to polecam gparted, w przeciwnym wypadku ...

Rozpoczynamy od odmontowania partycji umount /dev/sdX.
Wykonujemy sprawdzenie systemu plików e2fsc -f /dev/sdX.
Zmniejszamy system plików do pożądanego rozmiaru resize2fs /dev/sdX rozmiar (rozmiar możemy podać w blokach, megabajtach M, gigabajtach G np. 2G).
Zmniejszamy rozmiar partycji (ja daję rozmiar partycji trochę większy niż ustawiony powyżej za pomocą polecenia resize2fs - mam wówczas gwarancję, że partycja nie będzie za mała).
Czyli fdisk /dev/sdX, wyświetlamy informację o partycji przez opcję p, usunięcie wybranej partycji przez opcję d i podanie numeru partycji do usunięcia.
Założenie partycji tego samego typu i o mniejszym rozmiarze n, w moim przypadku p (primary), początek partycji w tym samym miejscu więc albo numer bloku od którego się zaczynała albo enter jeżeli jest to pierwsza partycja.
Wprowadzamy nowy rozmiar partycji więc np. +2G (partycja o rozmiarze 2 GB, można też korzystać z megabajtów M).
Zapisujemy nową partycję w, wychodzimy z fdisk q.
Wykonujemy sprawdzenie systemu plików e2fsck -f /dev/sdX.
Jeszcze raz wykonujemy resize2fs /dev/sdX, żeby system plików całkowicie wypełnił partycję.
Ponowne e2fsck -f /dev/sdX.

Montujemy partycję mount /dev/sdX /katalog_montowania.

Powyższa procedura pozwoliła mi na zmniejszenie wielkości partycji bez utraty danych na niej zawartych.
Gdybym jednak miał na zmniejszanej partycji jakieś ważne dane to na pewno wykonałbym backup.

Powiększenie partycji ext4

Gdy mamy komfort dostępu fizycznego do serwera można skorzystać z gparted, w pozostałych sytuacjach należy:

Odmontować partycję którą chcemy powiększyć umount /dev/sdX.
Sprawdzić gdzie zaczyna się i kończy partycja przez fdisk /dev/sdX.
Wyświetlenie wszystkich informacji przez wprowadzenie p i ich skopiowanie np. do notatnika.
Usunięcia partycji, którą chcemy powiększyć przez naciśnięcie d, a następnie wprowadzenie jej numeru.
Zapisanie zmian przez w, stworzenie nowej partycji przez opcję n.
Wybranie tego samego typu partycji jak był poprzednio primary/extended.
Wprowadzenie bloku, w którym ma się partycja zaczynać (powinien być taki sam jak ten wypisany we wcześniejszym kroku za pomocą p).
Wprowadzamy nowy rozmiar przez wprowadzenie wartości wraz z typem np. +5G, +1024M itp.
Zapisanie zmian przez opcję w.
Wykonanie fsck na powiększonej partycj e2fsck -f /dev/sdX.
Rozszerzenie systemu plików do nowej wielkości przez resize2fs /dev/sdX.
Ponowne podmontowanie partycji mount -a lub mount /dev/sdX /ścieżka_do_katalogu_montowania.

W powyższy sposób udało mi się zwiększyć rozmiar partycji bez utraty danych na niej zapisanych.

niedziela, 19 stycznia 2014

Linux konwertowanie mp4 do mp3

W celu konwertowania mp4 do mp3 zainstalowałem program soundconverter (środowisko graficzne gnome).
Po instalacji zmodyfikowałem ustawienia w preferencjach, aby pliki wynikowe były zapisywane w formacie mp3.

Zdaję sobie sprawę z tego, że istnieje możliwość konwertowania z konsoli, ale z doświadczenia wiem, że po kilku miesiącach zapominam z jakich przełączników korzystałem.

Najłatwiejszym rozwiązaniem jest wiec instalacja programu, który będzie pamiętał wszystkie parametry za nas.

Linux konwertowanie audiobook do mp3

W celu konwertowania audiobooków (pliki w formacie cda) do mp3, zainstalowałem następujące pakiety za pomocą apt-get install:
sound-juicer
gstreamer0.10-ffmpeg
gstreamer0.10-lame


Po uruchomieniu sound-juicer niezbędne było zmodyfikowanie ustawień w preferencjach (ustawienie pliku wyjściowego na mp3).