Przydatne proste skrypty dla linuxa

Na niniejszej stronie gromadzone są proste skrypty dla systemów operacyjnych linux / unix.

Jeśli chcesz, żeby znalazł się tutaj również Twój skrypt, bądź zmodyfikowałeś już istniejący, przyślij go wraz z opisem.

  1. Zamiana nazw plików z liter dużych na małe

  2. Zamiana spacji w nazwach plików na podkreślenia

  3. Zmiana nazwy rozszerzenia z htm na html w wielu plikach

  4. Zamiana ciągu znaków w zawartości wielu plików rekurencyjnie

  5. Usunięcie nieznaczących zer z ciągu liczb w pliku

  6. Poszukiwanie określonego pliku rekurencyjnie

  7. Poszukiwanie ciągu znaków w wielu plikach i katalogach rekurencyjnie

  8. Porównanie i wyszukiwanie rekurencyjnie plików identycznych z danym plikiem wzorcem

  9. Wyszukiwanie i liczenie liczby plików i katalogów z prawami r, w, x dla zalogowanego użytkownika

  10. Przeszukiwanie manuali względem określonego słowa kluczowego

  11. Usuwanie określonego pliku rekurencyjnie

  12. Liczenie ilości wierszy w pliku

  13. Liczenie ilości plików w wielu katalogach rekurencyjnie

  14. Liczenie ilości katalogów w danym katalogu lub rekurencyjnie

  15. Sprawdzanie z jaką dystrybucją linuksa pracujemy

  16. Pakowanie i rozpakowywanie tarem, gzipem i bzipem2

  17. Mirrorowanie stron WWW

  18. Automatyczne nabijanie głosów w ankietach

  19. Pobranie ciągu znaków (np. adresów e-mail) z plików html i umieszczenie ich w jednym pliku tekstowym

  20. Automatyczne obliczanie ilości rozwiązań na stronie Skrypty

  21. Radar do wykrywania zalogowanych znajomych

  22. Usprawnienie interfejsu menadżera okien screen

  23. Umieszczenie każdego słowa z pliku w osobnej linii w innym pliku

  24. Ograniczenie wpisywania komentarza do 100 znaków oraz wyświetlanie informacji ile jeszcze znaków można wpisać.

  25. Przenoszenie katalogów lub grup plików pomiędzy dwoma komputerami w sieci

  26. Kopiowanie jednej partycji/dysku na drugą partycję/dysk z zachowaniem uprawnień, linków itp.

  27. Automatyczne pobieranie plików wideo na przykładzie dzienników TVP

  28. Przeliczanie numeracji adresów IP na postać 32 bitowa i vice versa

  29. Automatyczne udzielanie odpowiedzi "yes" na pytanie jakie zadaje skrypt

  30. Reguła procmaila do odfiltrowywania spamu z użyciem SpamAssassin

  31. Statystyka działania SpamAssasin

  32. Reguła procmaila do usuwania robaków i wirusów internetowych na przykładzie robaka swen

  33. Konwersja folderów poczty z formatu KMail na Sylpheed Claws

  34. Usuwanie wszystkich procesów danego użytkownika

  35. Konwersja DOSowego pliku tekstowego na linuksowy i vice versa

  36. Liczba Pi

  37. Wysyłanie komunikatów poprzez mówiącą krowę

  38. Zmiana właściciela i uprawnień wszystkich plików i katalogów w podanym miejscu

  39. Automatyczny update repozytoriów CVS w podanych katalogach

  40. Skrypt do refaktoryzacji CVS

  41. Konwersja daty z języka angielskiego na polski

  42. Skrypt do przypominania np. o zmianie taśm do backupu

  43. Synchronizacja katalogów FTP w jedną stronę

  44. Skrypt powiadamiający o zdarzeniu (np. o nadchodzącej poczcie) poprzez włączenie "śniegu" na ekran

  45. Skrypt pokazujący pogodę na dzień jutrzejszy

  46. Skrypt pokazujący na ekranie losowy komiks z http://userfriendly.pl

  47. Skrypt przekazujący na stdout wylosowany argument

  48. Skrypt sprawdzający styl programu w Javie

  49. Automatyczne kontrolowanie czasu zalogowania i blokowanie logowania użytkowników

  50. Łączenie się z internetem spod konsoli tekstowej

  51. Podział łącza na kilku użytkowników z możliwością przypisania im różnych przepustowości

  52. Kierowanie ruchem w sieci pod linuksem

  53. Konfigurowanie podstawowych ustawień firewalla na przykładzie iptables



Zamiana nazw plików z wielkich liter na małe

Problem: Chcemy zmienić wielkość liter w wielu plikach o różnych nazwach z wielkich liter na małe. Np. mamy w katalogu NAZWA1.HTM, NAZWA2.HTM itd., a chcemy mieć nazwa1.htm, nazwa2.htm itd.

Ilość rozwiązań: 4

Rozwiązanie 1:

export IFS="
"
for file in *; do mv ${file} `echo ${file} | tr "A-Z" "a-z"`; done

Prosta modyfikacja pozwala na zamianę małych liter na duże:

export IFS="
"
for file in *; do mv ${file} `echo ${file} | tr "a-z" "A-Z"`; done

Nadesłał 07-09-2003 Robert Jaroszuk <zim@iq,pl>


Rozwiązanie 2:

Tworzymy plik np. o nazwie tolower i w nim umieszczamy:

#!/usr/bin/perl -w

die "ARGV?" unless ($#ARGV+1);

for $i (@ARGV)
{
   $j="\L$i";
   unless ($i eq $j) {
       system "mv", "$i", "$j";
   }
}

Uwagi: uruchamianie odbywa się poprzez ./tolower *html . (tolower powinien mieć atrybut pliku wykonywalnego, jeśli nie ma to chmod +x tolower). Oczywiście zamiast *html możemy podstawiać inne interesujące nas nazwy plików lub wszystkie: *.

Nadesłał 08-09-2003 Adam Kolany <dr.a.kolany@wp,pl>


Rozwiązanie 3:

Z wielkich liter na małe:

for stary in *.HTM ; do
  nowy="$(echo $stary | tr '[:upper:]' '[:lower:]')"
  mv "$stary" "$nowy"
done

Z małych na wielkie:

for stary in *.HTM ; do
  nowy="$(echo $stary | tr '[:lower:]' '[:upper:]')"
  mv "$stary" "$nowy"
done

Uwagi: Zamiast *.HTM można oczywiście podstawiać inne nazwy... "Klasy '[:upper:]' i '[:lower:]' powinny się zachowywać poprawnie z lokalizacją".

Nadesłał 08-09-2003 Michał Jaegermann <michal@gortel,phys,ualberta,ca>


Rozwiązanie 4:

Z wielkich liter na małe:

 rename 'y/A-Z/a-z/' *

Z małych na wielkie:

 rename 'y/a-z/A-Z/' *

Uwagi: Pod różnymi dystrybucjami linuksa są różne komendy rename o różnej składni. Powyższa występuje np. pod Debianem i wykorzystuje wyrażenia perla.

Nadesłał 12-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Zamiana spacji w nazwach plików na podkreślenia

Problem: Chcemy zamienić spacje w nazwach plików na podkreślenia, czyli zamienić nazwy: "nazwa pliku przed zmianą.txt" na "nazwa_pliku_po_zmianie.txt".

Ilość rozwiązań: 3

Rozwiązanie 1:

find ./ -type f -exec rename 's/ /_/g' {} \;

Nadesłał 02-09-2003 max <max.k@wp,pl>


Rozwiązanie 2:

for i in *\ * ; do mv "$i" "${i//\ /_}" ; done

Nadesłał 02-09-2003 Artur Gawryszczak <gawrysz@camk,edu,pl>
Zmodyfikował 02-09-2003 Krystian Piećko <messor@poczta,fm>
Zmodyfikował 02-09-2003 Marcin 'Qrczak' Kowalczyk <qrczak@knm,org,pl>


Rozwiązanie 3:

find . -name "* *" | while read; do
  mv "$REPLY" "${REPLY// /_}"
done

Nadesłał 11-09-2003 Marcin 'Qrczak' Kowalczyk <qrczak@knm,org,pl>


Zmiana nazwy rozszerzenia z htm na html w wielu plikach

Problem: Chcemy zamienić htm na html w nazwach wielu plików, czyli zamienić nazwy: "nazwa_pliku_przed_zmianą.htm" na "nazwa_pliku_po_zmianie.html". Problem jest analogiczny do opisanego powyżej problemu zamiany spacji na podkreślenia, więc rozwiązania poniżej to raczej wersja dla "opornych"... Jednakże występują tu również nowe, inne rozwiązania.

Ilość rozwiązań: 4

Rozwiązanie 1:

for i in `find katalog_z_plikami_htm -name '*.htm'`; do mv "$i" "${i}l"; done

Uwagi: Zamiast katalog_z_plikami_htm może być też oczywiście np. kropka ".".

Nadesłał 19-08-2000 Piotr Piątkowski <kompas@ceti,com,pl>
Zmodyfikował 22-12-2003 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 2:

for a in *.htm; do mv $a `basename $a .htm`.html; done

Nadesłał 19-08-2000 Sławomir Siwek <slawomir,siwek@pse,pl>


Rozwiązanie 3:

mmv \*.htm #1.html

Uwagi: Program mmv ma większe możliwości niż pokazany trywialny przykład.

Nadesłał 20-08-2000 Jakub Turski <yacoob@supersonic,plukwa,net>


Rozwiązanie 4:

rename 's/\.htm$/.html/' *.htm

Uwagi: Pod różnymi dystrybucjami linuksa są różne komendy rename o różnej składni. Powyższa występuje np. pod Debianem i wykorzystuje wyrażenia perla. Inny typ komendy rename (występuje np. pod Slackware czy Fedorą) można użyć następująco: rename .htm .html *.htm  - niestety, w tym przypadku zakładamy, że w środku nazwy nie występuje .htm .

Nadesłał 12-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Zamiana ciągu znaków w zawartości wielu plików rekurencyjnie

Problem: Jak zamienić ciąg znaków w wielu plikach rekurencyjnie? Np. w plikach tekstowych html.
(BTW, użytkownicy M$ Windows mają do dyspozycji co najmniej 2 programy freeware do tego służące: String Find & Replace i polski Znajdź i Zamień).

Ilość rozwiązań: 7

Rozwiązanie 1:

Gdy pliki są tylko w jednym katalogu:

perl -pi -e 's/wzorzec/zamiennik/g' *.html

Rekurencyjnie:

find -name '*.html' |xargs perl -pi -e 's/wzorzec/zamiennik/g'

Uwagi: Pod niektórymi systemami należy jako pierwszy argument polecenia find podać ścieżkę, od której zaczynamy wyszukiwanie plików (np. "."). W przypadku gdy wzorzec i zamiennik jest adresem e-mail należy poprzedzić @ znakiem \, czyli \@, gdyż perl interpretuje @ przed nazwami tablic. Wzorzec jest wyrażeniem regularnym dlatego we wzorcu również . (kropki) poprzedzamy (chronimy) \, czyli \. . Zamiennik jest już zwykłym napisem, zatem tam przed kropkami nie trzeba wstawiać \, ale jego ewentualne wstawienie nie będzie szkodzić.

Nadesłał 19-08-2000 Piotr Piątkowski <kompas@ceti,com,pl>


Rozwiązanie 2:

Jeśli w poszukiwanym ciągu znaków występują znaki, których użyliśmy jako separator po operatorze s, wówczas musimy użyć innych znaków separacyjnych dla operatora s, takich które nie pojawiają się w poszukiwanym ciągu znaków np. { }:

find . -name '*.html' |xargs perl -pi -e 's{\Q<script src=..\..\E}{ }g'

Uwagi: Tekst między \Q i \E jest brany "dosłownie", bez zważania na występujące tam znaki, dzięki temu kropki będą traktowane jako kropki - standardowo w wyrażeniu regularnym kropka oznacza dowolny znak. W podanym przykładzie chcemy usunąć z plików html wyrażenie "<script src=..\.."

Nadesłał 19-08-2000 Piotr Piątkowski <kompas@ceti,com,pl>


Rozwiązanie 3:

for f in "`find . -name '*.html'`"; do 
	sed -e 's/wzorzec/zamiennik/g' "$f" > /tmp/tymczas; 
	mv /tmp/tymczas "$f";
done

Uwagi:  Bez znaków "" dookoła komendy find wyjście z find byłoby dzielone po wszelkich odstępach, czyli nazwy plików ze spacjami byłyby podzielone na kawałki.

Nadesłał 22-01-2004 fv <fake@cybax,com>
Zmodyfikował 22-01-2004 Jacek Pospychała <tri10o@bsod,org>
Zmodyfikował 23-01-2004 Marcin 'Qrczak' Kowalczyk <qrczak@knm,org,pl>


Rozwiązanie 4:

find -name '*.html' | while read; do
  perl -i -pe 's/wzorzec/zamiennik/g' "$REPLY"
done

Uwagi: Takie same jak w rozwiazaniu 1. Wadą tego skryptu jest uruchamianie perla dla każdego pliku osobno zamiast hurtem dla kilku jak w rozwiązaniu 1.

Nadesłał 23-01-2004 Marcin 'Qrczak' Kowalczyk <qrczak@knm,org,pl>


Rozwiązanie 5:

Zamiana w pojedynczym pliku:

sed 's/wzorzec/zamiennik/g' < plik.do.zmiany > plik.po.zmianie

Uwagi: Podobne jak w rozwiazaniu 1. Jeśli we wzorcach występują znaki '/' można też dać np. ':' jako rozdzielacz. Jeśli chcemy zastąpić: 'firma S.A.' przez '<B>firma S.A.</B>' to wstawiamy: 's:firma S.A.:<B>&</B>:g'

Nadesłał 08-09-2002 Marcin Wojtczuk <fastviper@poczta,onet,pl>


Rozwiązanie 6:

Zamiana w pojedynczym pliku:

cat plik.do.zmiany |sed 's/wzorzec/zamiennik/g' > plik.po.zmianie
Zamiana w pojedynczym pliku wielu różnych wyrażeń.

wersja 1:

cat plik.do.zmiany | sed "s/wzorzec1/zamiennik1/g;s/wzorzec2/zamiennik2/g;s/wzorzec3/zamiennik3/g" > plik.po.zmianie

wersja 2:

cat plik.do.zmiany | sed -e s/wzorzec1/zamiennik1/g -e s/wzorzec2/zamiennik2/g -e s/wzorzec3/zamiennik3/g > plik.po.zmianie
Uwagi: Podobne jak w rozwiazaniu 1.

Nadesłał 08-09-2002 Zbigniew Cofała <Zbigniew@Cofala,com>
Zmodyfikował 24-01-2004 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>
Zmodyfikował 08-09-2002 Jacek Pospychała <tri10o@bsod,org>
Zmodyfikował 08-09-2002 Grzegorz Niewęgłowski <grzegorz@quatri,.pl>


Rozwiązanie 7:

Jeśli chcemy wykonać jakieś działanie edycyjne (np. zamienić ciąg znaków) w plikach zawierających jakiś tekst, możemy zaprząc do tego Vim-a w sposób następujący:

for f in $(grep -r tekst * | grep -v "~" | cut -f 1 -d ":" | uniq); do 
vim -c "%s/tekst/drugitekst/g" -c "wq" $f;done

Uwagi: w ten sposób vim-ujemy tylko pliki zawierające dany tekst, tylko raz, i pomijając pliki tymczasowe.

Nadesłał 22-08-2005 Bartłomiej Górny <bartek@redpoint,mn,pl>


Usunięcie nieznaczących zer z ciągu liczb w pliku

Problem: W pliku tekstowym mamy ciąg liczb które zaczynają się od zer, np. 000000000182021, 000000028012300. Chcemy usunąć nieznaczące zera, tak aby liczby przybrały postać: 182021, 28012300.

Ilość rozwiązań: 1

Rozwiązanie 1:

cat plik | sed -e 's/^0*//' > plik2

Uwagi: Usunięcie nastąpi jeśli żaden inny ciąg znaków nie będzie poprzedzał tych liczb w poszczególnych wierszach w pliku.

Nadesłał 04-02-2002 Tomasz Poradowski <weirdo@poczta,onet,pl>
Zmodyfikował 22-12-2003 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Poszukiwanie określonego pliku rekurencyjnie

Problem: W jaki sposób wyszukać określony plik w strukturze katalogów pod linuksem?

Ilość rozwiązań: 5

Rozwiązanie 1:

find / -type f -name plik | grep plik > plik.txt

Uwagi: Gdy nie chcemy przeszukiwać wszystkich katalogów w systemie to zmieniamy / na ścieżkę do katalogu, który chcemy przeszukać wraz z podkatalogami np. na . .

Nadesłał 05-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 2:

locate plik

Uwagi: locate wyszukuje pliki w okresowo aktualizowanej bazie danych w systemie.

Nadesłał 05-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 3:

whereis nazwa_polecenia

Uwagi: whereis wyszukuje pliki binarne, źródłowe i strony man dla danego polecenia. Whereis przeszukuje wyłącznie standardowe katalogi, w których znajdują się pliki binarne, źródłowe i man.

Nadesłał 05-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 4:

which nazwa_programu

Uwagi: Which pobiera serię nazw programów i drukuje pełne ścieżki programów, które powłoka by wywołała, aby je uruchomić. Robi to symulując przeszukiwanie przez powłokę zmiennej środowiskowej $PATH.

Nadesłał 05-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 5:

type nazwa

Uwagi: Komenda type opisuje jak każdy operand nazwa byłby interpretowany, gdyby go użyć jako komendy. type wyświetla informacje o operandzie identyfikując go jako wbudowany do shella, jako funkcję, alias, zahashowana komendę, słowo kluczowe; może też wyświetlić ścieżkę dostępu do operandu nazwa.

Przykłady:

~$ type ls
ls is aliased to `/usr/bin/ls $LS_OPTIONS'
~$ type ls
ls is aliased to `ls --color=auto'
~$ type ls
ls is /usr/xpg4/bin/ls
~$ type l
l is an alias for 'ls -l'

Nadesłał 14-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Poszukiwanie ciągu znaków w wielu plikach i katalogach rekurencyjnie

Problem: Chcemy znaleźć poszukiwany ciąg znaków w wielu plikach, w wielu podkatalogach. Chodzi o zidentyfikowanie, w których plikach jest poszukiwane wyrażenie.

Ilość rozwiązań: 3

Rozwiązanie 1:

grep -r -H wyrazenie *

Nadesłał 08-09-2003 <slaweks@seznam,cz>


Rozwiązanie 2:

find . -name "*.html" -exec grep -H wyraz {} \;

Nadełał 08-09-2003 <slaweks@seznam,cz>


Rozwiązanie 3:

find /www -type f -exec grep -H -i string {} \;

Nadesłał 08-09-2003 Robert Jaroszuk  <zim@iq,pl>


Porównanie i wyszukiwanie rekurencyjnie plików identycznych z danym plikiem wzorcem

Problem: W jaki sposób wyszukać pliki i porównać z plikiem podanym jako wzorzec (nazwa, zawartość) w drzewie katalogów podanych przez użytkownika?

Ilość rozwiązań: 1

Rozwiązanie 1:

a) przeanalizować zadanie:
wykonać: wyszukiwanie plików w katalogu podanym przez użytkownika dla każdego znalezionego wykonać:
porównaj plik_znaleziony plik_wzorca

b) użyć prostych poleceń, przetłumaczyć sobie na angielski
find pliki w katalog
for każdy znaleziony do
compare znaleziony wzorzec

Sprawdzić czy są takie polecenia jakie byśmy chcieli: find, for, compare
dwa pierwsze - strzał w dziesiątkę, pozostaje trzecie:
bash:~$ man compare
Nie ma strony manuala dla compare
bash:~$ apropos compare
[...]
cmp (1) - compare two files byte by byte
[...]

c) przeczytać znalezione manuale
man find, help for, man cmp

d) dostosować (b) do formalizmów programów find, for, cmp

wzorzec="/home/croopnick/wzorzec.txt"
katalog="/home/zosia/pliki/"
for znaleziony in `find $katalog -type f`; do
 if cmp "$znaleziony" "$wzorzec"; then
  echo "$znaleziony pasuje do wzorca"
 fi
done

d') w trakcie implementacji...
pojawiło się coś nowego "if".
Sprawdzić co to: help if

e) w postaci skryptu:

#!/bin/sh

if [ $# -lt 2 ] ; then 
 echo "parametry: katalog wzorzec"
 exit 1
fi
wzorzec="$2"
katalog="$1" 
for znaleziony in `find $katalog -type f`; do
        if cmp "$znaleziony" "$wzorzec" >/dev/null; then
                echo "$znaleziony pasuje do wzorca"
        fi
done

# :)

Nadesłał 22-04-2004 Jacek Pospychala  <tri10o@bsod,org>


Wyszukiwanie i liczenie liczby plików i katalogów z prawami r, w, x dla zalogowanego użytkownika

Problem: W jaki sposób obliczyć ilość plików i katalogów rekurencyjnie z podkatalogami danego katalogu i wyświetlić ilość plików i katalogów z danymi prawami r, w, x dla zalogowanego użytkownika?

Ilość rozwiązań: 1

Rozwiązanie 1:

#!/bin/sh

dir=/
temp=`mktemp`
ilekat=0
ileplik=0
ile=0
xplik=0
rplik=0
wplik=0
xkat=0
rkat=0
wkat=0

if test "$1" = "-help"
then
echo prawa [-f][-d][katalog]
echo skrypt oblicza ilosc plikow i katalogow rekurencyjnie z podkatalogami od podanego katalogu
echo i wyswietla ilosc plikow i katalogow z danymi prawami r,w,x dla zalogowanego uzytkownika
echo -f wyswietlaj statystyke dla plikow
echo -d wyswietlaj statystyke dla katalogow
elif test $# -eq 0
then
echo brak parametrow
elif test $# -gt 3
then
echo za duzo parametrow
elif test "$1" != "-d" && test "$1" != "-f"
then
echo nieznany parametr $1
elif test $# -eq 2 && test ! -d $2 && test "$2" != "-f" && test "$2" != "-d"
then
echo bledny parametr
elif test "$2" != "-d" && test "$2" != "-f" && test "$2" != "" && test ! -d $2 
then
echo nieznany parametr $2
elif test $# -eq 3 && test -d $2 && test -d $3
then
echo bledne parametry
elif test $# -eq 3 && test !  -d $3
then 
echo $3 nie jest katalogiem

else
if test -d $3
then
dir=$3
fi
if test -d $2
then
dir=$2
fi

find $dir -name '*' -print > $temp 

while read a 
do

ile=`expr $ile + 1`
if test  -d $a 
then

ilekat=`expr $ilekat + 1`
if test -x $a
then
xkat=`expr $xkat + 1`
fi
if test -r $a
then
rkat=`expr $rkat + 1`
fi
if test -w $a
then
wkat=`expr $wkat + 1`
fi

else
ileplik=`expr $ileplik + 1`

if test -x $a
then
xplik=`expr $xplik + 1`
fi
if test -r $a
then
rplik=`expr $rplik + 1`
fi
if test -w $a
then
wplik=`expr $wplik + 1`
fi

fi

done < $temp

if test "$1" = "-f" || test "$2" = "-f"
then
echo przeanalizowanych plikow: $ileplik
echo ilosc plikow wykonywalnych: $xplik
echo ilosc plikow do odczytu: $rplik
echo ilosc plikow do pisania: $wplik
fi
if test "$1" = "-d" || test "$2" = "-d"
then
echo przeanalizowanych katalogow: $ilekat
echo ilosc katalogow z prawem wykonywania: $xkat
echo ilosc katalogow z prawem do odczytu: $rkat
echo ilosc katalogow z prawem do zapisu: $wkat
fi
fi 

Uwagi: Skrypt oblicza ilość plików i katalogów rekurencyjnie z podkatalogami podanego katalogu i wyświetla ilość plików i katalogów z danymi prawami r, w, x dla zalogowanego użytkownika
Opcje:
-f wyświetlaj statystykę dla plików
-d wyświetlaj statystykę dla katalogów
-help wyświetla pomoc skryptu

To_do: Autor skryptu chciałby się dowiedzieć w jaki sposób ten skrypt uprościć. Jeśli napiszesz prostszą wersję tego skryptu proszę ją nadesłać do opublikowania na tej stronie.

Nadesłał 06-05-2005 Bartłomiej Draba <drabek@o2,pl >


Przeszukiwanie manuali względem określonego słowa kluczowego

Problem: W jaki sposób znaleźć opis komendy w sytuacji gdy "man komenda" nie daje rezultatu?

Ilość rozwiązań: 1

Rozwiązanie 1:

apropos słowo_kluczowe

lub

man -k słowo_kluczowe

Uwagi: Każda strona manuala posiada nazwę i krótki opis. Apropos wyszukuje nazwy i opisy zawierające zadane słowo_kluczowe. Domyślnie słowo_kluczowe jest traktowane jako wyrażenie regularne. Krótkie opisy manuali, gdy znamy ich nazwę, można też wyświetlić komendą whatis nazwa lub man -f nazwa .

Nadesłał 05-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Usuwanie określonego pliku rekurencyjnie

Problem: Mamy strukturę katalogów i chcemy usunąć z całego drzewa wszystkie pliki o nazwie "plik". Jak to zrobić?

Ilość rozwiązań: 3

Rozwiązanie 1:

find . -name plik -exec rm {} \; -print

Uwagi: Usuwa pliki o nazwie "plik" w katalogu bieżącym i jego podkatalogach. Istnieją lepiej dopracowane metody - patrz kolejne rozwiązania poniżej.

Nadesłał 29-04-2005 <pst0@poczta,onet,pl>
Zmodyfikował 30-04-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 2:

find . -type f -name plik -print | xargs rm

Uwagi: W przypadku rozwiązania nr 1 przy każdym pliku wywoływany będzie osobny rm, używając xargs unikamy tej wady, dzięki czemu przy dużej ilości plików skrypt wykona się szybciej i mniej obciąży zasoby komputera. Opcja -type f powoduje, że find wynajduje tylko zwykłe pliki (pominie katalogi o nazwie plik, chociaż rm bez dodatkowych opcji i tak by katalogów nie usunął).

Nadesłał 29-04-2005 Tomasz Kłoczko <kloczek@rudy,mif,pg,gda,pl>
Zmodyfikował 30-04-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 3:

find . -type f -name plik -print | sed 's/^/"/' | sed 's/$/"/' | xargs rm

Uwagi: xargs czyta ze standardowego wejścia listę argumentów rozdzielonych spacjami lub znakami nowej linii. Argumenty zawierające spacje czy znaki nowej linii mogą być chronione poprzez ujęcie ich w cudzysłów podwójny, pojedynczy lub w backslashe. Powyższa komenda zawiera zabezpieczenie przed problemem spacji czy znaku nowej linii ("entera") w nazwie pliku.

Nadesłał 30-04-2005 "Stanisław 'Dozzie' Klekot" <dozzie@dynamit,im,pwr,wroc,pl>
Zmodyfikował 30-04-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Liczenie ilości wierszy w pliku

Problem: Chcemy policzyć ile wierszy znajduje się w danym pliku.

Ilość rozwiązań: 1

Rozwiązanie 1:

wc -l plik

Nadesłał 08-01-2004 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>
Zmodyfikował 28-02-2004 Artur Gawryszczak <gawrysz@camk,edu,pl>


Liczenie ilości plików w wielu katalogach rekurencyjnie

Problem: Chcemy policzyć ile zwykłych plików mamy w podkatalogach danego katalogu.

Ilość rozwiązań: 1

Rozwiązanie 1:

find . -type f -maxdepth 10 | wc -l

Uwagi: parametr f pozwala na nie branie pod uwagę dowiązań symbolicznych i katalogów; maxdepth określa jaka głębokość poziomu katalogów jest uwzględniana, wartość maxdepth 0 oznacza by testy i akcje stosować tylko do argumentów wiersza poleceń.

Nadesłał  Peter Blomgren <blomgren@monster,stanford,edu>


Liczenie ilości katalogów w danym katalogu lub rekurencyjnie

Problem: Chcemy policzyć ile podkatalogów mamy w danym katalogu lub rekurencyjnie ile mamy katalogów w wielu podkatalogach danego katalogu.

Ilość rozwiązań: 5

Rozwiązanie 1:

ls -l| grep ^d| wc -l

Uwagi: Nie są uwzględniane w liczeniu dowiązania i katalogi ukryte; dodaj opcje -a po ls, żeby policzyć również katalogi ukryte w danym katalogu (niestety wraz z katalogami "." oraz ".."; jeśli nie chcesz ich liczyć patrz rozwiązanie 2 lub 3) oraz -R, jeśli chcesz liczyć rekurencyjnie.

Nadesłał  05-09-2003 Krystian Piećko <messor@poczta,fm>


Rozwiązanie 2:

ls -lAR| grep ^d| wc -l

Uwagi: Skrypt działa tak samo jak w "rozwiązaniu 1" dla opcji -laR do ls, ale nie liczy katalogów "." oraz "..".

Nadesłał  01-12-2003 Adam Osuchowski <adwol@polsl,gliwice,pl>


Rozwiązanie 3:

ls -laR | grep ^d | awk '{print $9}' | egrep -v '^\.{1,2}$' | wc -l

Uwagi: Skrypt działa tak samo jak w "rozwiązaniu 1" dla opcji -laR do ls, ale nie liczy katalogów "." oraz "..".

Nadesłał  23-09-2003 Marcin ``MySZ`` Sztolcman <msztol@poczta,onet,pl>


Rozwiązanie 4:

find . -type d | wc -l

Uwagi: bez parametru -maxdepth liczy bez ograniczeń wgłąb struktury katalogów rekurencyjnie, ponadto uwzględnia zawsze katalogi ukryte oraz katalog ".".

Nadesłał 10-09-2003 Artur Zabroński <scooty@osk-merkury,ath,cx>


Rozwiązanie 5:
find . -type d | egrep -v '^\.{1,2}$' | wc -l

Uwagi: Skrypt działa tak samo jak w "rozwiązaniu 4", ale nie liczy katalogu ".". Ponadto jeśli zamiast katalogu startowego (powyżej : . ) poda się pełną ścieżkę (np. /etc) skrypt zawsze da wynik o 1 większy, ponieważ liczy wtedy także katalog z którego zaczyna (gdy jest '.', to jest to wychwytywane przez egrep).

Nadesłał  23-09-2003 Marcin ``MySZ`` Sztolcman <msztol@poczta,onet,pl>


Sprawdzanie z jaką dystrybucją linuksa pracujemy

Problem: Jak sprawdzić z jaką dystrybucją linuksa mamy do czynienia? Jaka jest wersja linuksa?

Ilość rozwiązań: 1

Rozwiązanie 1:

#v+
for FILE in /etc/*version /etc/*release /etc/*issue; do
  test -e "$FILE" || continue
  echo "$FILE" | sed -e 's/.\(version\|release\)$//' -e 's,^/etc/,,'
  cat "$FILE"
done
#v-

Uwagi: Jeśli powyższy skrypt nie da odpowiedzi można jeszcze spróbować zebrać dodatkowe informacje o systemie i typie maszyny używając ciągu komend: echo $MACHTYPE; echo $HOSTTYPE; echo $OSTYPE; uname -a . Szczególnie pod FreeBSD powinno to pomóc uzyskać informacje o wersji systemu. Pod niektórymi shellami (np. tcsh) uruchomienie . nazwa_pliku może nie dać rezultatu, wówczas uruchamiamy source nazwa_pliku, a gdy i to polecenie zawiedzie wówczas skrypt wykonujemy w następujący sposób: sh nazwa_pliku.
Jeśli ta prosta heurystyka w wyżej przedstawionym skrypcie nie zadziała, wówczas trzeba zdać się na metody dedukcji ;) i sprawdzić parę rzeczy charakterystycznych dla dystrybucji: istnienie /var/log/packages i /sbin/{install,remove,upgrade,make}pkg wskazuje na Slackware lub pochodną, /etc/apt wskazuje na coś używającego apt (OIDP Fedora, na pewno Debian), /usr/ports występuje we FreeBSD i tak dalej. Czasem jeszcze gcc -v (jeśli jest zainstalowane w systemie) wyświetla m.in. info o rodzaju dystrybucji.

Nadesłał 08-05-2005 "Stanisław 'Dozzie' Klekot" <dozzie@dynamit,im,pwr,wroc,pl>
Zmodyfikował 08-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Pakowanie i rozpakowywanie tarem, gzipem oraz bzipem2

Problem: Jak spakować / rozpakować spakowane gzipem archiwum tar? Jak skompresować / zdekompresować skompresowane bzipem2 archiwum tar?

Ilość rozwiązań: 2

Rozwiązanie 1:

Komenda:

tar zxvf plik.tar.gz [lub plik.tgz]
rozpakuje archiwum tar, dekompresując je uprzednio z użyciem gzip (literka z opcji).
tar zcvf plik.tar.gz plik1 plik2 plik3 ... plikN
tworzy archiwum o nazwie plik.tar.gz złożone z podanych plików. Zamiast plików można podawać również katalogi.
tar lxvf plik.tar.bz2 [lub plik.tbz2]

rozpakowuje archiwum tar, dekompresując je uprzednio z użyciem bzip2 (literka l opcji).

tar lcvf plik.tar.bz2 plik1 plik2 plik3 ... plikN

utworzy archiwum tar i skompresuje je programem bzip2 . Zamiast plików można podawać również katalogi.

Uwagi: W przypadku plików niezarchiwizowanych tarem pakujemy odpowiednio gzip plik lub bzip2 plik a rozpakowujemy gunzip plik.gz lub bunzip2 plik.bz2 . Czasem jeszcze bywa używany program compress (rozszerzenie spakowanych plików .Z), kompresujemy z użyciem polecenia compress, a dekompresujemy uncompress.

Nadesłał 08-09-2003 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>
Zmodyfikował 24-09-2003 Marcin Dudek <Marcin@Dudek,eu,org>
Zmodyfikował 12-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 2:

Z użyciem mc (midnight commandera).

Pakowanie:

Wejdź do katalogu, którego zawartość rekurencyjnie chcesz spakować. Następnie: F2 i 3  w przypadku pakowania gzipem lub 4 w przypadku bzip2 . Pakowanie pojedynczych plików zaznaczonych klawiszem Insert: F2 i B w przypadku bzip2 lub Y w przypadku gzip.

Rozpakowywanie:

Najedź kursorem na plik, który chcesz rozpakować; F2 i Z lub zamiast tego na skompresowanym archiwum [Enter] (ewentualnie dodatkowo kursor w dół i kolejne [Enter], a następnie * lub Insert tyle razy ile potrzeba) i F5 - kopiowanie zawartości archiwum do katalogu jaki jest otwarty w sąsiednim oknie mc.

Uwagi: Jeśli nie masz zdefiniowanych klawiszy w mc wówczas klawisze funkcyjne możesz uruchamiać z użyciem Esc i cyfry odpowiadającej klawiszowi funkcyjnemu, np. Esc 2 = F2 .

Nadesłał 12-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Mirrorowanie stron WWW

Problem: Jak zrobić mirror stron WWW (stworzyć kopię lustrzaną strony WWW)?

Ilość rozwiązań: 1

Rozwiązanie 1:

Z użyciem wgeta.

Przykład:

wget -m -nv -k -K -E -nH -p -np --cut-dirs=1 -t 1000 -D wbc.lublin.pl -o $HOME/logiwget/logchemfanpl -P $HOME/web/chemia http://znik.wbc.lublin.pl/ChemFan/

Uwagi:

  1. -m
    --mirror, włącza opcje odpowiednie do tworzenia kopii lustrzanych (w wersji 1.9.1 wgeta jest równoważna użyciu -r -N -l 0 -nr, czyli włącza rekurencję, stosowanie znaczników czasu (nie pobiera ponownie plików, chyba że są nowsze niż lokalne), ustawia nieograniczony poziom rekurencji i zachowuje listingi katalogów FTP w postaci plików .listing. Pliki te zawierają nieprzetworzone listingi katalogów otrzymane z serwerów FTP. Pozostawienie ich może się przydać do celów diagnostycznych lub łatwego sprawdzenia zawartości katalogów zdalnego serwera (np. do sprawdzenia, że tworzona kopia lustrzana jest kompletna)). Dodatkowo można zażyczyć sobie konwersji odnośników, tak by całość nadawała się do przeglądania lokalnie (opcja -k). Taka konwersja nie sprawuje się dobrze, gdy wykorzystujemy znaczniki czasu, więc chcemy również, żeby Wget utworzył kopie oryginalnych plików HTML przed ich przekształceniem, stąd użycie opcji -K.
  2. -nv
    --non-verbose, wyłącza wypisywanie jak największej liczby komunikatów, bez trybu ciszy (komunikaty o błędach i podstawowe informacje będą nadal wypisywane).
  3. -k
    --convert-links, konwertuje odnośniki bezwzględne na względne, tzn. po zakończeniu pobierania konwertuje odnośniki w dokumencie tak, by nadawały się do lokalnego przeglądania. Dotyczy to nie tylko widzialnych odnośników hipertekstowych, ale każdej części dokumentu, która prowadzi do zewnętrznych materiałów, jak osadzone obrazki, odnośniki do arkuszy stylów, odnośniki hipertekstowe do zawartości innej niż HTML, itp.

    Każdy odnośnik będzie zmieniony na jeden z dwu sposobów:

    o Odnośniki do plików, które zostały ściągnięte przez Wget zostaną zmienione tak, by odwoływały się do pliku, na jaki wskazują, jako odnośniki względne.

    Przykład: jeśli ściągnięty plik /foo/doc.html jest powiązany z z /bar/img.gif, również ściągniętym, to odnośnik w doc.html zostanie zmieniony tak, by wskazywał na ../bar/img.gif. Ten rodzaj przekształcenia działa bezproblemowo dla dowolnej kombinacji katalogów.

    o Odnośniki do plików, które nie zostały ściągnięte przez Wget zostaną zmienione tak, by zawierały nazwę hosta i ścieżkę bezwzględną miejsca, na które wskazują.

    Przykład: jeśli ściągnięty plik /foo/doc.html jest powiązany z z /bar/img.gif (lub z ../bar/img.gif), to odnośnik w doc.html zostanie zmieniony tak, by wskazywał na http://host-name/bar/img.gif.

    Z tego powodu, przeglądanie lokalne działa niezawodnie: jeśli powiązany plik był ściągnięty, to odnośnik wskazuje na jego lokalną nazwę, a jeśli nie był, to na pełny adres internetowy (nie pojawia się popsuty odnośnik). Konwersja pierwotnych odnośników na odnośniki względne zapewnia nam możliwość przesuwania pobranej hierarchii katalogów do innego katalogu.

    Proszę zauważyć, że dopiero na samym końcu pobierania Wget może rozpoznać, które odnośniki zostały ściągnięte. Z tego powodu, opcja -k wykonuje swoją pracę dopiero po zakończeniu wszystkich pobrań.

  4. -K
    --backup-converted, podczas konwersji pliku zachowuje kopię zapasową pierwotnej wersji z przyrostkiem .orig. Opcja ta wpływa na zachowanie opcji -N oraz -E.
  5. -E
    --html-extension, jeśli pobierany jest plik typu text/html a jego URL nie kończy się wyrażeniem regularnym \.[Hh][Tt][Mm][Ll]?, to opcja ta spowoduje dodanie rozszerzenia .html do lokalnej nazwy pliku. Przydatne, na przykład, gdy tworzymy kopię lustrzaną witryny, która używa stron .asp, ale chcemy, by pozyskane strony dawały się przeglądać za pomocą własnego serwera Apache. Innym dobrym zastosowaniem jest pobieranie wyjścia generowanego przez skrypty CGI. URL typu http://site.com/article.cgi?25 zostanie zachowany jako article.cgi?25.html.

    Proszę zauważyć, że pliki o zmienionych w ten sposób nazwach będą ponownie pobierane za każdym razem gdy będziemy odświeżać kopię lustrzaną witryny. Dzieje się tak, ponieważ Wget nie potrafi stwierdzić, że lokalny plik X.html odpowiada zdalnemu URL-owi X (gdyż nie wie, że ten URL tworzy wyjście typu text/html). Chcąc uniknąć ponownego pobierania, trzeba użyć -k i -K, tak by oryginalna wersja pliku została zachowana jako X.orig.

  6. -nH
    --no-host-directories, zakazuje tworzenia katalogu o nazwie hosta. Domyślnie, -r http://fly.srk.fer.hr/ spowoduje stworzenie struktury katalogów zaczynającej się od fly.srk.fer.hr/, gdzie trafi cała reszta. Ta opcja wyłącza takie zachowanie.
  7. -p
    --page-requisites, pobiera wszystkie pliki graficzne itp. potrzebne by poprawnie wyświetlić stronę HTML.

    Opcja ta powoduje, że Wget ściągnie wszystkie pliki niezbędne do poprawnego wyświetlenia danej strony HTML. Obejmuje to takie rzeczy jak grafikę, dźwięki i powiązane arkusze stylów.

    Przy zwykłym trybie pracy, podczas pobierania pojedynczej strony HTML, ewentualne powiązane dokumenty, które mogą być potrzebne do poprawnego jej wyświetlenia, nie są pobierane. Pomóc może użycie opcji -r z -l, ale ponieważ Wget normalnie nie odróżnia dokumentów zewnętrznych od włączonych, na ogół pozostaje się z ,,oskubanymi dokumentami'', którym brakuje potrzebnych elementów towarzyszących.

    Przy użyciu opcji -p Wget zachowa się tak, jakby podano opcję -r, ale zostanie pobrana tylko pojedyncza strona i jej elementy. Program nie będzie podążał za odnośnikami z tej strony do zewnętrznych dokumentów. Faktycznie, do ściągania pojedynczej strony i wszystkich towarzyszących jej elementów (nawet jeśli leżą one na odrębnych serwerach WWW) i upewnienia się, że całość lokalnie poprawnie się wyświetla, można oprócz -p skorzystać z kilku dodatkowych opcji:

    wget -E -H -k -K -p http://<ośrodek>/<dokument>

    gdzie -H, --span-hosts zezwala na przejście do obcych maszyn podczas pracy rekurencyjnej.

    Warto wiedzieć, że Wget uważa za odnośnik do dokumentu zewnętrznego każdy URL podany w znaczniku "<A>", "<AREA>" lub "<LINK>", oprócz "<LINK REL="stylesheet">".

  8.  -np
    --no-parent, zakazuje wychodzenia poza katalog nadrzędny.  Powoduje, że Wget przy pobieraniu rekurencyjnym nigdy nie wchodzi do katalogu nadrzędnego. Przydatna opcja, gdyż gwarantuje, że ściągane będą tylko pliki poniżej pewnego poziomu.
  9. --cut-dirs=liczba
    Ignoruje podaną liczbę składowych katalogu. Przydatne do precyzyjnego sterowania katalogami, w których będą składowane pliki z pobierania rekurencyjnego.

    Weźmy, na przykład, katalog ftp://ftp.xemacs.org/pub/xemacs/. Jeżeli pobierzemy go z -r, to lokalnie zostanie zachowany jako ftp.xemacs.org/pub/xemacs/. Mimo że opcja -nH pozwala na usunięcie części ftp.xemacs.org/, nadal utkniemy z pub/xemacs. Tu właśnie z pomocą przychodzi --cut-dirs. Powoduje, że Wget "nie widzi'' zadanej liczby składowych zdalnego katalogu. Oto kilka przykładów pokazujących, jak działa opcja --cut-dirs.

     bez opcji -> ftp.xemacs.org/pub/xemacs/
    -nH -> pub/xemacs/
    -nH --cut-dirs=1 -> xemacs/
    -nH --cut-dirs=2 -> .
    --cut-dirs=1 -> ftp.xemacs.org/xemacs/

    Jeśli chcemy po prostu pozbyć się struktury katalogów, to opcja ta jest podobna do kombinacji -nd i -P. Jednak --cut-dirs, w przeciwieństwie do -nd, nie pozbywa się podkatalogów -- na przykład, przy -nH --cut-dirs=1, podkatalog beta/ będzie, zgodnie z oczekiwaniami, umieszczony w xemacs/beta.

  10. -t liczba
    --tries=liczba, ustawia liczbę ponawiania prób na liczbę. Dla nieskończonego ponawiania podajemy 0 lub inf.
  11. -D lista_domen
    --domains=lista_domen, lista oddzielonych przecinkami akceptowanych domen.
    Ustala domeny do których program może przechodzić. lista_domen jest listą separowaną przecinkami. Proszę zauważyć, że ta opcja nie włącza -H.
  12. -o dziennik
    --output-file=dziennik
    Rejestruje wszystkie komunikaty w pliku dziennika. Normalnie są zgłaszane na standardowym wyjściu błędów.
  13. -P prefiks
    --directory-prefix=prefiks
    Ustawia prefiks katalogów na prefiks. Directory-prefix oznacza katalog, w którym zostaną zapisane wszystkie inne pliki i katalogi, tzn. wierzchołek drzewa pobierania. Domyślnym prefiksem jest . (katalog bieżący).
  14. --follow-ftp
    Podąża za odnośnikami FTP z dokumentów HTTP. Bez tej opcji Wget będzie ignorował wszelkie odnośniki do FTP.

Proszę zauważyć, że powyższy przykład użycia programu Wget nie pozwala na pobieranie kodu źródłowego skryptów czy innego kodu server-side. Wszystkie nieHTMLowe rozszerzenia w plikach typu text/html (np. .CGI, .ASP) zostaną zapisane jako pliki html. W celu wykonania dokładnej kopii lustrzanej wszystkich plików należy mirrorować Wgetem przez FTP.

Najwygodniej uruchamiać polecenie do mirrorowania z crona. Zawartość crontab pozwalająca na tworzenie kopii lustrzanej o 21:05 każdego dnia:

# MIN HOUR DAY MONTH DAYOFWEEK COMMAND

05 21 * * * $HOME/skr/mirror 2> logmirror

gdzie w pliku mirror umieszczamy polecenia (to oczywiście tylko przykład):

wget -m -nv -k -K -E -nH --cut-dirs=1 -np -t 1000 -D wbc.lublin.pl -o $HOME/logiwget/logchemfan.pl -p http://znik.wbc.lublin.pl/ChemFan/ && \
cd $HOME/web/chemfan.pl/arch && \
wget -m -nv -k -K -E -nH -np --cut-dirs=2 -t 1000 -D lists.man.lodz.pl -o $HOME/logiwget/logchemfanarchive.pl -p http://lists.man.lodz.pl/pipermail/chemfan/ && \
cp $HOME/web/domirrora/chemfan/Archiwum/index.html $HOME/web/chemfan.pl/Archiwum/
cd chemfanftp && \
wget -m -nv -k -K -E -nH -np --cut-dirs=4 -t 1000 -D ftp.man.lodz.pl --follow-ftp -o $HOME/logiwget/logchemfanarchiveftp -p ftp://ftp.man.lodz.pl/pub/doc/LISTY-DYSKUSYJNE/CHEMFAN/ && \
cd .. && \
perl -pi -e 's{\Qftp://ftp.man.lodz.pl/pub/doc/LISTY-DYSKUSYJNE/CHEMFAN\E}{./chemfanftp/}g' index.html

Plikowi mirror nadajemy chmod 755.

Skomplikowanie powyższego przykładu wynika z niedoskonałości wersji Wgeta 1.9.1. W zasadzie nie jest możliwe z użyciem tej wersji Wgeta poprawne mirrorowanie stron WWW (tak aby nie ściągnąć przy okazji rzeczy niechcianych, a wszystkie odnośniki były poprawnie przekonwertowane), których zawartość znajduje się nie tylko na jednym serwerze, lecz pod kilkoma całkiem różnymi domenami, z użyciem tylko jednej sesji Wgeta. W związku z tym, w powyższym przykładzie wszystkie fragmenty składowe portalu ChemFan znajdujące się pod różnymi domenami pobierane są z użyciem oddzielnych sesji Wgeta, a następnie w wyniku tego dwa pliki HTML muszą mieć jeszcze zmodyfikowane linki, aby połączyć mirror w całość. W przypadku strony, której zawartość się nie zmienia dokonujemy tego z użyciem komendy cp, która nadpisuje plik zmirrorowany kopią z ręcznie poprawionym linkiem, natomiast w przypadku strony z często zmieniającą się zawartością posługujemy się skryptem perla aby poprawić link.
Dodatkowo zrezygnowano tutaj z użycia opcji -P Wgeta, którą zastąpiono komenda cd, gdyż wersja Wgeta 1.9.1 i starsze mają buga, który powoduje niewłaściwą konwersję linków w przypadku użycia tej opcji w takim jak powyżej przykładzie. Bug ten został usunięty w wersji 1.10 Wgeta, która jednakże w chwili pisania tego tekstu jest jeszcze w stadium alpha.

Wskazane by było aby przyszłe wersje Wgeta umożliwiały po opcjach -D i -I wpisywanie nie tylko domen, ale i katalogów (ścieżek), a opcja -np brała pod uwagę katalogi wpisane po tych opcjach.

Hrvoje Niksic, autor Wgeta, obiecuje zająć się niektórymi z tych problemów w wersji 1.11 Wgeta.

W przypadku niektórych stron WWW przy powtórnym mirrorowaniu Wget nieprawidłowo przekonwertuje linki, które za pierwszym razem przekonwertował prawidłowo. Dzieje się tak przykładowo przy mirrorowaniu strony http://znik.wbc.lublin.pl/Mineraly/ . Na stronie tej znajduje się animowany gif: http://znik.wbc.lublin.pl/ChemFan/Gify/ChemFan.gif . Przy mirrorowaniu za pierwszym razem Wget (w wersji 1.9.1) prawidłowo przekonwertował link obrazka na http://mineraly.feedle.com/Gify/ChemFan.gif , jednakże mirrorując te same strony powtórnie (celem odświeżenia mirrora) Wget utworzył fałszywy link http://znik.wbc.lublin.pl/Mineraly/Gify/ChemFan.gif .

Tego buga odkryłem dopiero wczoraj (02-05-2005), dlatego nie ma jeszcze - w chwili pisania tego tekstu - dostępnych wersji Wgeta uwzględniających ten problem. Hrvoje jednak szybko się uwinął i jeszcze tego samego dnia kiedy zgłosiłem tego buga opublikował łatki nie dopuszczające do powstania powyżej opisanego problemu:

Index: src/http.c
===================================================================
RCS file: /pack/anoncvs/wget/src/http.c,v
retrieving revision 1.173
diff -u -r1.173 http.c
--- src/http.c  2005/04/28 13:56:31     1.173
+++ src/http.c  2005/05/02 14:58:53
@@ -2318,6 +2318,11 @@
                             local_filename);
                  free_hstat (&hstat);
                  xfree_null (dummy);
+                 /* The file is the same; assume that the links have
+                    already been converted.  Otherwise we run the
+                    risk of converting links twice, which is
+                    wrong.  */
+                 *dt |= DT_DISABLE_CONVERSION;
                  return RETROK;
                }
              else if (tml >= tmr)
Index: src/retr.c
===================================================================
RCS file: /pack/anoncvs/wget/src/retr.c,v
retrieving revision 1.95
diff -u -r1.95 retr.c
--- src/retr.c  2005/04/16 20:12:43     1.95
+++ src/retr.c  2005/05/02 14:58:55
@@ -761,7 +761,7 @@
          register_download (u->url, local_file);
          if (redirection_count && 0 != strcmp (origurl, u->url))
            register_redirection (origurl, u->url);
-         if (*dt & TEXTHTML)
+         if ((*dt & TEXTHTML) && !(*dt & DT_DISABLE_CONVERSION))
            register_html (u->url, local_file);
        }
     }
Index: src/wget.h
===================================================================
RCS file: /pack/anoncvs/wget/src/wget.h,v
retrieving revision 1.57
diff -u -r1.57 wget.h
--- src/wget.h  2005/04/27 21:08:40     1.57
+++ src/wget.h  2005/05/02 14:58:55
@@ -233,7 +233,8 @@
   HEAD_ONLY            = 0x0004,       /* only send the HEAD request */
   SEND_NOCACHE         = 0x0008,       /* send Pragma: no-cache directive */
   ACCEPTRANGES         = 0x0010,       /* Accept-ranges header was found */
-  ADDED_HTML_EXTENSION = 0x0020         /* added ".html" extension due to -E */
+  ADDED_HTML_EXTENSION = 0x0020,       /* added ".html" extension due to -E */
+  DT_DISABLE_CONVERSION = 0x0040       /* disable link conversion */
 };
 
 /* Universal error type -- used almost everywhere.  Error reporting of

Nadesłał 08-07-2003 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>
Zmodyfikował  12-04-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>
Zmodyfikował  29-04-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>
Zmodyfikował  03-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Automatyczne nabijanie głosów w ankietach

Problem: W jaki sposób nabić głosy w sondzie / ankiecie? ;)

Ilość rozwiązań: 1

Rozwiązanie 1:

while true; do
wget http://www.mbank.com.pl/aktualnosci_vote.pl?vote=1 -o /dev/null
sleep 5  # zeby nie bylo... :-)
done

Uwagi: Nabijanie tego typu możliwe jest tylko, gdy można głosować wielokrotnie z tego samego IP. Kiedyś tak można było w mBanku, nie używano tam nawet ciasteczek (podobno początkowo było blokowanie po IP, ale ludzie narzekali, że przecież więcej klientów korzysta z jednego komputera...). Skrypt prezentowany wyłącznie w celach edukacyjnych.

Nadesłał  28-06-2001 Radosław Stachowiak  <radek@alter,pl>


Pobranie ciągu znaków (np. adresów e-mail) z plików html i umieszczenie ich w jednym pliku tekstowym

Problem: W jaki sposób z pliku html wydobyć automatycznie adresy e-mail będące w tym pliku i umieścić je w jednej kolumnie w pliku tekstowym?

Ilość rozwiązań: 1

Rozwiązanie 1:

grep 'mailto:' plik |sed -e 's/^.*mailto://' |sed -e 's/">.*$//' > plik.txt

Uwagi: Zamiast plik podstawiamy nazwę przeszukiwanego pliku, można też oczywiście *

Nadesłał  13-07-2001 Radosław Stachowiak  <radek@alter,pl>
Zmodyfikował  08-09-2003 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Automatyczne obliczanie ilości rozwiązań na stronie Skrypty

Problem: W jaki automatycznie policzyć ile skryptów i złożonych komend znajduje się na niniejszej stronie?

Ilość rozwiązań: 3

Rozwiązanie 1:

wget -q -O - http://skrypty.feedle.com/ | grep '<b>Ilość rozwiązań:' \
|sed -e 's/^.*<b>Ilość rozwiązań://' |sed -e 's/<\/b>.*$//' | \
awk '{sum+=$1}; END{print sum}'

Uwagi: Kreska po opcji -O oznacza wypisanie ściągniętych danych na standardowe wyjście (czyli na wejście tego skryptu) zamiast do jakiegoś pliku.

Nadesłał  17-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>
Zmodyfikował  17-05-2005 MichalR <mrot@neostrada,pl>


Rozwiązanie 2:

 wget -q -O - http://skrypty.feedle.com/ | \
 awk '/<b>Ilość rozwiązań:/{sum += $3}; END{print sum}'

Uwagi: To, że po liczbie są jeszcze różne "dodatki" w przypadku 'awk' nie ma znaczenia. Z dokumentacji, sekcja "Conversion": "A string is converted to a number by interpreting any numeric prefix of the string as numerals: `"2.5"' converts to 2.5, `"1e3"' converts to 1000, and `"25fix"' has a numeric value of 25."
Jak ktoś chce być bardziej ostrożny z możliwymi wariantami "white space" to mozna użyć funkcji 'match' i wyciąć tylko cyfry przy pomocy RSTART, RLENGTH, albo uciąć przez 'sub' wszystkie "nie-cyfry" na początku linii i sumować 'sum += $0'. W każdym bądź razie nic poza awk do zliczania nie jest potrzebne.

Nadesłał 18-05-2005 Michał Jaegermann <michal@gortel,phys,ualberta,ca>


Rozwiązanie 3:

wget -q -O - http://skrypty.feedle.com/ | perl -e '$n = 0; while(<>){$n+=$1 if /Ilość rozwiązań:\s+(\d+)/;}print "$n\n";'

Nadesłał 17-05-2005 Lech Lorens


Radar do wykrywania zalogowanych znajomych

Problem: W jaki sposób zrobić skrypt radar do wykrywania zalogowanych znajomych?

Ilość rozwiązań: 4

Rozwiązanie 1:

ff ()   {
          until finger @host_name1.jakis_adres.com | grep fragles
          do
          sleep 300
          done && \
          echo @@@@@@@@@@@@@@@@@@@@@@@@@@@
          echo Fragles jest na host_name1!
          echo @@@@@@@@@@@@@@@@@@@@@@@@@@@
        }
  
fp ()   {
          until finger @host_name2.jakis_adres.pl | grep duzers
          do
          sleep 300
          done && \
          echo @@@@@@@@@@@@@@@@@@@@@@@@@@@
          echo Duzers jest na host_name2!
          echo @@@@@@@@@@@@@@@@@@@@@@@@@@@
        }
             

Uwagi: Jak widać są to funkcje, którą każdą uruchamiamy oddzielnie. Oczywiście radar taki ma sens tylko wtedy, gdy fingerowanie użytkowników na danym serwerze nie jest zablokowane.

Nadesłał 04-06-1995 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Rozwiązanie 2:

while true
do
if [ "$a" = "" ]
then
finger @host_name1.jakis_adres.com | grep fragles && a=1 &&
echo @@@@@@@@@@@@@@@@@@@@@@@@@@@
echo Fragles jest na host_name1!
echo @@@@@@@@@@@@@@@@@@@@@@@@@@@
fi
sleep 3
if [ "$b" = "" ]
then
finger @host_name2.jakis_adres.pl | grep duzers && b=1 &&
echo %%%%%%%%%%%%%%%%%%%%%%%%%%
echo Duzers jest na host_name2!
echo %%%%%%%%%%%%%%%%%%%%%%%%%%
fi
sleep 3
if [ "$c" = "" ]
then
finger @host_name3.jakis_adres.net | grep gorg && c=1 &&
echo ########################
echo Gorg jest na host_name3!
echo ########################
fi
# tu można wstawiać kolejne człony, analogiczne do powyższych
sleep 18
done &

Uwagi: Skrypt po wykryciu jednej osoby działa dalej sprawdzając pozostałe. Osobę raz znalezioną już pomija. Jeśli chcesz umieścić jakiś dodatkowy komentarz, to przykładowo po a=1 dodaj && echo 'text'. Powyższy skrypt zapisujemy w pliku radar, nadajemy mu chmod 700 radar, uruchamiamy pisząc radar. Chodzi oczywiście w tle. :)

Nadesłał 25-10-1995 Artur Backiel artbac@cksr,ac,bialystok,pl


Rozwiązanie 3:

#!/bin/bash
declare -i KONIEC=0     # deklaruj zmienna
declare -i FRAGLES=0    # deklaruj zmienna
declare -i DUZERS=0     # deklaruj zmienna 
until let $KONIEC       # czekaj az zmienna=0
do                      # czekajac wykonuj petle

   finger @host_name1.jakis_adres.com > andy.bash.tmp
   # szukaj pierwszej osoby lub na pierwszym hoscie
   if { grep fragles andy.bash.tmp >> /dev/null } then  
   {
        echo                                      # jak go wykryles to
        echo @@@@@@@@@@@@@@@@@@@@@@               # daj znac
        echo Fragles jest w sieci !
        echo @@@@@@@@@@@@@@@@@@@@@@
        FRAGLES=1;                                # i sygnalizuj koniec
   }
   fi

   if { grep duzers andy.bash.tmp >> /dev/null } then  
   {
        echo                                      # jak go wykryles to
        echo @@@@@@@@@@@@@@@@@@@@@                # daj znac
        echo Duzers jest w sieci !
        echo @@@@@@@@@@@@@@@@@@@@@
        DUZERS=1;                                 # i sygnalizuj koniec
   }
   fi

   KONIEC=DUZERS+FRAGLES;   # jesli chcesz aby skrypt zakonczyl po znalezieniu
                            # pierwszej osoby to uzyj znaku +

#  KONIEC=DUZERS*FRAGLES;   # jesli chcesz aby skrypt zakonczyl po znalezieniu
                            # wszystkich osob to uzyj znaku *

# tych czlonow if ... fi mozna dolaczyc ile chcesz

sleep 1000            # czekaj jakis czas
done                  # zamkniecie petli while
rm andy.bash.tmp

Nadesłał  11-06-1995 Artur Jasowicz <arturj@interaccess,com>
Zmodyfikował  13-08-1995 Artur Jasowicz <arturj@interaccess,com>


Rozwiązanie 4:

#!/bin/bash
declare -i KONIEC=0	# deklaruj zmienna
declare -i FRAGLES=0	# deklaruj zmienna
declare -i DUZERS=0	# deklaruj zmienna
declare -i TMP=0	# zmienna tymczasowa
until let $KONIEC	# czekaj az zmienna=0
do			# czekajac wykonuj petle

   finger @host_name1.jakis_adres.com 2> /dev/null > ".andy.tmp"  # utworz nowy plik
   finger @host_name2.jakis_adres.net 2> /dev/null >> ".andy.tmp" # w ten sposob sprawdzasz
                                                                  # kilka maszyn
   # szukaj pierwszej osoby lub na pierwszym hoscie
   if { grep fragles ".andy.tmp" >> /dev/null } then
   {
        FRAGLES=1;		# sygnalizuj koniec
   }
   fi

   if { grep duzers ".andy.tmp" >> /dev/null } then
   {
        DUZERS=1;		# sygnalizuj koniec
   }
   fi

   KONIEC=DUZERS+FRAGLES;
		# jesli chcesz aby skrypt zakonczyl po znalezieniu
		# pierwszej osoby to uzyj znaku +

#  KONIEC=DUZERS*FRAGLES;
		# jesli chcesz aby skrypt zakonczyl po znalezieniu
		# wszystkich osob to uzyj znaku *

TMP=FRAGLES+DUZERS;

if { let $TMP } then		# jesli ktokolwiek zostal wykryty
{
   echo				# wydrukuj poczatek bannera
   echo @@@@@@@@@@@@@@@@@@@@@@

   if { let $FRAGLES } then
   {
      echo Fragles jest w sieci !
   } fi

   if { let $DUZERS } then {
      echo Duzers jest w sieci !
   } fi

   echo @@@@@@@@@@@@@@@@@@@@@@	# zakoncz banner
}
fi
	# tych czlonow if ... fi mozna dolaczyc ile chcesz


if { ! let $KONIEC } then	# jesli jeszcze nie skonczyles...
{
   sleep 300			# to zaczekaj jakis czas przed powtorzeniem petli
}
fi

done			# zamkniecie petli while
rm ".andy.tmp"   	# niekonieczne, ale oszczedza miejsce na koncie

Nadesłał  21-08-1995 Artur Jasowicz <arturj@interaccess,com>


Usprawnienie interfejsu menadżera okien screen

Problem: Co zrobić, żeby były wyświetlane numery okien screena?

Ilość rozwiązań: 1

Rozwiązanie 1:

W pliku .screenrc umieść linię:

caption always "%1`@%H %c | %-Lw%{= BW}%50>%n* %t%{-}%+Lw%<"

Nadesłał 14-05-2005 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Umieszczenie każdego słowa z pliku w osobnej linii w innym pliku

Problem: W jaki sposób umieścić słowa z danego pliku w osobnej linii?

Ilość rozwiązań: 1

Rozwiązanie 1:

cat plik | tr -cs '[a-zA-Z0-9]' '[\n*]' > plik.txt

Nadesłał 10-09-2003 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Ograniczenie wpisywania komentarza do 100 znaków oraz wyświetlanie informacji o tym, ile jeszcze znaków można wpisać.

Problem: Chcemy napisać prosty skrypt,  gdzie m.in. użytkownik ma wpisywać swój komentarz. Komentarz ten nie może przekroczyć powiedzmy 100 znaków. Za każdym wprowadzonym znakiem u góry ekranu będzie podawana liczba, która informuje, ile znaków można jeszcze wpisać.

Ilość rozwiązań: 2

Rozwiązanie 1:

W C można tak:

#v+

#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#define CHARS_COUNT     100
int main()
{
       int counter = 0;
       char buf[CHARS_COUNT + 1];
       struct termios term_new;
       struct termios term_old;
       tcgetattr(STDIN_FILENO, &term_old);
       term_new = term_old;
       term_new.c_lflag &= ~ICANON;
       tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_new);
       memset(buf, 0 , sizeof(buf));
       printf("Chars: %d ... %s", counter, buf);
       while (counter < CHARS_COUNT) {
               buf[counter] = getchar();
               counter++;
               printf("\033[1GChars: %d ... %s", counter, buf);
       }
       printf("\a\n");
       tcsetattr(STDIN_FILENO, TCSANOW, &term_old);
       return 0;
}

#v-

Nadesłał 02-08-2003 Artur Zabroński <scooty@osk-merkury,ath,cx>


Rozwiązanie 2:

#v+
#!/bin/bash
a=0
koment=""
while true; do
 read -s -n 1 b
 a=$(($a+1))
 case "$b" in
   ".")
   break
   ;;
   "")
   koment=$(echo "$koment ")
   ;;
   *)
   koment=$(echo "$koment$b")
   ;;
 esac
 if [ $a -eq 100 ]; then
   break
 fi
 clear
 echo "zostało znaków: $((100-a)), kropka kończy komentarz"
 echo "$koment"
done
clear
echo "wprowadziłes: $koment"
#v-
Uwagi: "trochę to pokrętne, bo bash w tym trybie nie chce wczytywać spacji, widzi ją jako pusty znak, dlatego ta kropka"

Nadesłał  03-08-2003 Paweł Gancarz  <paga@provider,pl>
Zmodyfikował 05-08-2003 Tomasz Pędrys <tkp@tkp,org>


Przenoszenie katalogów lub grup plików pomiędzy dwoma komputerami w sieci

Problem: Jak przenieść katalogi i/lub pliki pomiędzy dwoma komputerami w sieci?

Ilość rozwiązań: 3

Rozwiązanie 1:

Na 1 maszynie podwieszamy na porcie netcata:

(192.168.1.1)$ nc -l -p 2048 | tar -zxvf -
teraz na drugiej maszynie archiwizujemy dane i wysyłamy netcatem na
maszynę 1:
(192.168.1.2)$ tar -zcvf - katalog | nc 192.168.1.1 2048

Nadesłał 10-09-2003 Robert Jaroszuk <zim@iq,pl>


Rozwiązanie 2:

tar czf - katalog | ssh 192.168.1.1 tar xzf -

Nadesłał 10-09-2003 Marcin 'Qrczak' Kowalczyk <qrczak@knm,org,pl>


Rozwiązanie 3:

rsync -ax -e ssh katalog_lokalny user@maszyna:katalog_zdalny

Uwagi: Powyżej przedstawiono wersje interaktywną, wersja nieinteraktywna wymaga skonfigurowania rsyncd. Można w ten sposób odświeżać mirrory dysków zarówno w obrębie komputerów, jak i po sieci. Można też dodatkowo użyć opcji -S (ona jest od efektywnego traktowania tzw. "sparse files"), wówczas byłoby: rsync -axS ,  a jeśli niektóre z kopiowanych plików są hardlinkowane, to jeszcze -H można dopisać.

Nadesłał 12-09-2003 Artur Gawryszczak <gawrysz@camk,edu,pl>


Kopiowanie jednej partycji/dysku na drugą partycję/dysk z zachowaniem uprawnień, linków itp.

Problem: Jak skopiować jedną partycję/dysk na drugą partycję/dysk z zachowaniem uprawnień, linków itp.?

Ilość rozwiązań: 2

Rozwiązanie 1:

( cd / && tar cf - bin etc boot inne katalogi ) | ( cd /mnt/drugidysk && tar xpvf - )

Nadesłał 10-09-2003 Robert Jaroszuk <zim@iq,pl>


Rozwiązanie 2:

cp -a katalog_źródłowy katalog_docelowy

Nadesłał 10-09-2003 Marcin 'Qrczak' Kowalczyk <qrczak@knm,org,pl>


Automatyczne pobieranie plików wideo na przykładzie dzienników TVP

Problem:  Jak automatycznie, codziennie pobierać pliki wideo asf z zapisanymi w nich serwisami informacyjnymi TVP: Panoramą, Teleexpressem i Wiadomościami?

Ilość rozwiązań: 4

Rozwiązanie 1:

#!/bin/sh
cd $HOME/tvp

date=`date +'%Y-%m-%d'`

wget -O page.html http://ww2.tvp.pl/tvppl/119.dzialy
cat page.html | grep -E 'href=".*\.asf"[^<]{1,}</a>' | \
        sed -e 's/.*href="\([^"]*\)[^>]*>\([^ ]*\).*/http:\/\/ww2.tvp.pl\/tvppl\/\1 -O \2/' | \
        while read comm; do
                wget $comm-$date.asf
        done
rm page.html

Uwagi: Jeśli chcesz pobierać pliki do głównego katalogu domowego możesz usunąć (lub zahaszować) linię cd $HOME/tvp. Najlepiej odpalać skrypt automatycznie z crona wówczas codziennie będziemy mieli u siebie na dysku aktualne wydanie Panoramy, Teleexpressu i Wiadomości. :)

Nadesłał 16-09-2003 Damian Pietras <daper@daper,net>


Rozwiązanie 2:

Zawartość wiadomosci.sh :

#cd $HOME/tvp

date=`date +'%Y-%m-%d'`
program=$1

if ! echo "$program" | grep -i -E '^(panorama|teleexpress|wiadomości)$' &>/dev/null
then
        echo "Uzycie: $0 PROGRAM"
        echo "PROGRAM to panorama, teleexpress lub wiadomości"
        exit 1
fi

wget -O page.html http://tvp.pl/
url=`cat page.html | grep -E -i "href=\"video.*$program" | head -1 | \
        sed -e 's/.*href="\(.*\.asf\)".*/\1/'`
wget -O "$program-$date.asf" "http://tvp.pl/$url"
rm page.html

Uwagi: W momencie gdy powstawało "Rozwiązanie 1" TVP wystawiała codziennie do ściągnięcia na swojej stronie WWW tylko jedno wydanie Panoramy, Wiadomości i Teleexpressu. Obecnie zaś dostępnych jest kilka wydań tych dzienników z różnych pór danego dnia.
Powyższy skrypt pozwala na pobieranie ostatniej Panoramy, Teleexpressu lub Wiadomości.
Używa się go tak:

sh wiadomosci.sh teleexpress

Ściąga Teleexpress w tym przypadku.

Nadesłał 15-04-2005 Damian Pietras <daper@daper,net>


Rozwiązanie 3:

Zawartość wiadomosci.pl :

#v+
#!/usr/bin/perl

open INPUT, "wget -O - http://ww2.tvp.pl/tvppl/119.dzialy |";

while (<INPUT>) {
    if (/href="(.+\.asf)"([^<]{1,})<\/a>/) {
	$url = "http://ww2.tvp.pl/tvppl/$1";
	$tytul = $2;
	$tytul =~ s/^.+">//;
	$tytul =~ s/,//;
	$tytul =~ s/&nbsp;/ /;
	$tytul =~ s/ /-/g;
	system("wget $url -O $tytul.asf");
    }
}
#v-

Uwagi: Skrypt pobiera wszystkie dzienniki jakie są w chwili uruchomienia skryptu na stronie TVP. Nazwa pliku zawiera nazwę dziennika oraz datę i godzinę w formie takiej jaka widnieje na stronie TVP. Uruchamianie: perl wiadomosci.pl

To_do: Format daty TVP zapisuje na swoich stronach dość niekonsekwentnie, bowiem raz godzinę podaje z dokładnością do minuty (18.30), a raz tylko godziny (22), bez roku, a miesiąc cyframi rzymskimi (np. Teleexpress-19-IV.asf, Wiadomości-19.30-19-IV.asf ), przez to zapis daty i godziny wychodzi na pierwszy rzut oka mniej czytelny, niż gdyby zawsze był zapisywany w ten sam sposób. Ponadto łatwiej by takie pliki było sortować w katalogu po dacie czy nazwie dziennika. Jeśli zatem ktoś zmodyfikuje skrypt, aby pliki były zapisywane np. w taki sposób:
19-04-2005-17.00-Teleexpress.asf
19-04-2005-19.30-Wiadomości.asf
lub w taki:
Teleexpress-17.00-19-04-2005.asf
Wiadomości-19.30-19-04-2005.asf
bądź w taki:
Teleexpress-19-04-2005-17.00.asf
Wiadomości-19-04-2005-19.30.asf
proszę
nadesłać rozwiązanie do opublikowania na tej stronie.

Update To_do 12-05-2005: Skrypt w Rozwiązaniu 4 zapisuje dzienniki w formacie Nazwadziennika_dzienmiesiacanazwamiesiacaslownie_godzinaiminuty.asf ,  np. Panorama_12maja_18.30.asf . W dalszym ciągu jednak możesz nadesłać swoją wersję skryptu.

Nadesłał 16-04-2005 Maciej Witkowiak <ytm@elysium,pl>


Rozwiązanie 4:

Zawartość tvp.plx:

#! /usr/bin/perl
$base = "http://ww2.tvp.pl/tvppl/" ;
open INHTML, ("wget -q -O - $base" . "119.dzialy |") ;
%months = (I	=> "stycznia",
	   II	=> "lutego",
	   III	=> "marca",
	   IV	=> "kwietnia",
	   V	=> "maja",
	   VI	=> "czerwca",
	   VII	=> "lipca",
	   VIII	=> "sierpnia",
	   IX	=> "września",
	   X	=> "października",
	   XI	=> "listopada",
	   XII	=> "grudnia"
) ;


while(<INHTML>) {
	if($_ =~ /class="wartoText.*\.asf"/) {
		$_ =~ /href="([^"]*).*(Pano[^\s]*|Wiad[^\s]*|Tele[^\s]*)\s+(\d\d\.\d\d)?[^\d]*(\d+)[^XVI]*([XVI]+)/ ;
		my ($input, $name, $time, $day, $mth, $plik) = ("","","","","") ;
		$input = $1 if defined $1 ;
		$name = $2 if defined $2 ;
		$time = $3 if defined $3 ;
		$day = $4 if defined $4 ;
		$month = $5 if defined $5 ;
		my $output = "$name" . "_$day$months{$month}" . ($time ne ""?"_$time":"") . ".asf\n" ;
		#$output =~ s/Wiadomo.ci/Wiadomosci/ ;		# odkomentować, by usunąć 'ś' z nazwy pliku
		#$output =~ s/pa.dziernika/pazdziernika/ ;	# analogicznie października => pazdziernika
		#$output = lc $output ;				# odkomentować, by nazwa pliku wyjściowego składała się z małych liter
		system("wget $base$input -O $output") ;
	}
}

Uwagi: Powyższy skrypt zapisuje dzienniki w formacie Nazwadziennika_dzienmiesiacanazwamiesiacaslownie_godzinaiminuty.asf ,  np. Panorama_12maja_18.30.asf

Nadesłał 11-05-2005 Lech Lorens


Przeliczanie numeracji adresów IP na postać 32 bitowa i vice versa

Problem:  Jak przeliczyć adres IP na postać 32 bitową i na odwrót?

Ilość rozwiązań: 1

Rozwiązanie 1:

Przeliczenie ze standardowego adresu IP na postać 32 bitową:

perl -e 'print unpack("N",pack("C4",split(/\./,"111.222.333.444")));'

Uwagi: Zamiast 111.222.333.444 wpisujemy numer IP, który chcemy przeliczyć.

Przeliczenie z postaci 32 bitowej na postać standardową:

perl -e 'print join(".",unpack("C4",pack("N",1234567890)))."\n";'

Uwagi: Zamiast 1234567890 wpisujemy postać 32 bitową numeru IP, który chcemy przeliczyć.

Nadesłał 21-05-1999 Szymon Sokół <szymon@uci,agh,edu,pl>


Automatyczne udzielanie odpowiedzi "yes" na pytanie jakie zadaje skrypt

Problem:  Skrypt zadaje nam pytanie i oczekuje na nie odpowiedzi "yes" lub "no". Chcemy skrypt uruchamiać z crona w środku nocy musimy więc zautomatyzować proces udzielania odpowiedzi.

Ilość rozwiązań: 2

Rozwiązanie 1:

/usr/bin/yes | /$PATH_TO_SCRIPT/scrypt.sh
Uwagi: Program yes da tyle odpowiedzi "yes" ile pojawi się pytań-czytań w skrypcie.

Nadesłał 18-09-2003 Piotr Sietnik <psi@pk,mofnet,gov,pl>


Rozwiązanie 2:

Jeśli zestaw odpowiedzi jest stały, to np.
(echo y; echo coś innego) | skrypt

Nadesłał 17-09-2003 Marcin 'Qrczak' Kowalczyk <qrczak@knm,org,pl>


Reguła procmaila do odfiltrowywania spamu z użyciem SpamAssassin

Problem:  W jaki sposób usunąć lub zapisać do oddzielnego pliku pocztę przefiltrowaną przez SpamAssassin?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku .procmailrc:

SHELL=/bin/sh
# MAILDIR=$HOME/Maildir
# LOGFILE=$HOME/procmail.log
VERBOSE=yes

# Ustawiamy ograniczenie filtrowania do postów mniejszych niż 250 kB. 
# Większe mogłyby SA łatwo przeciążyć. 

:0fw: spamassassin.lock
* < 256000
| spamassassin -a

# Ustawiamy, żeby plik z pocztą, który uzyskał powyżej 7 spamowych gwiazdek
# był kasowany.
:0:
* ^X-Spam-Level: \*\*\*\*\*\*\*
/dev/null

#Pliki z pocztą mające 3 i 4 gwiazdki umieszczamy w oddzielnym pliku
:0:
* ^X-Spam-Level: \*\*\*(\*?)$
spam-3-4-gwiazdkowy

#Pliki z pocztą mające 5, 6 i 7 gwiazdek umieszczamy w jeszcze innym pliku
:0:
* ^X-Spam-Status: Yes
spam-5-6-7-gwiazdkowy
Uwagi: SpamAssassin ma ustawione oznaczanie postów jako spam standardowo na 5 punktów, ponieważ jednak przychodziło do mnie sporo spamów mających mniej niż 5 punktów, dlatego filtruję takie posty do oddzielnego pliku i przeglądam co jakiś czas mailxem (wywołanie np. mailx -f  spam-3-4-gwiazdkowy). Więcej o regułach procmaila.

Nadesłał 23-09-2003 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Statystyka działania SpamAssasin

Problem:  W jaki sposób sprawdzić ile e-maili spamowych i niespamowych oznaczył SpamAssassin?

Ilość rozwiązań: 1

Rozwiązanie 1:

#!/bin/bash

# Zmienne
LOG=plik_z_logiem.log

# Funkcje
function dni {
ALL=`grep -i -z '' $LOG | awk -F " " '{print $1 " " $2}' | sort -u`
echo "Dostepne sa zapisy z dni:"
echo -e "$ALL\n"
echo "Wybierz date np. `echo -e "$ALL" | head -n 2`"

read data
}

function pusta_data {
if [  "$data" = '' ]
 then
 echo "Zestawienie obejmuje wszystkie dostepne w logu dni"
fi
}

function menu {
echo "Wybierz:  1-wiadomosci przetworzone"
echo "          2-rozpoznane jako SPAM"
echo "          3-wiadomosci czyste"
echo "          4-wiadomosci pominiete"
echo "          5-zestawienie "
echo "          6-wprowadzenie nowej daty"
echo "          7-KONIEC"
}

# Skrypt
dni
menu

while read
do
case $REPLY in
1)
pusta_data
echo "Przetworzone: `grep -z -i "$data" $LOG | grep -z -i 'processing' |wc
-l`"
;;
2)
pusta_data
echo "Rozpoznany SPAM: `grep -z -i "$data" $LOG | grep -z -i 'identified'
|wc -l`"
;;
3)
pusta_data
echo "Czyste: `grep -z -i "$data" $LOG | grep -z -i 'clean' |wc -l`"
;;
4)
pusta_data
echo "Pominiete: `grep -z -i "$data" $LOG | grep -z -i 'skipped' |wc -l`"
;;
5)
pusta_data
echo "--------------------"
echo "Zestawienie dla: $data"
echo "Przetworzone: `grep -z -i "$data" $LOG | grep -z -i 'processing' |wc
-l`"
echo "Rozpoznany SPAM: `grep -z -i "$data" $LOG | grep -z -i 'identified'
|wc -l`"
echo "Czyste: `grep -z -i "$data" $LOG | grep -z -i 'clean' |wc -l`"
echo "Pominiete `grep -z -i "$data" $LOG | grep -z -i 'skipped' |wc -l`"
echo "--------------------"
;;
6)
dni
;;
7)
echo "Bye"
exit
;;
*)
menu
esac
done

Uwagi: Jednym z warunków poprawnego działania jest ustawienie sysloga, aby zapisywał informacje od procesu SpamAssassin do oddzielnego pliku. Może zaistnieć potrzeba dostrojenia skryptu, chodzi głównie o pola z datą, czyli numery pól w linii: awk -F " " '{print $1 " " $2}' . Jeśli plik nie jest binarny, to można z grepa usunąć parametr "-z".

Nadesłał 18-05-2005 Marcin Wasilewski <marcinwasilewski@poczta,onet,pl>


Reguła procmaila do usuwania robaków i wirusów internetowych na przykładzie robaka swen

Problem:  W jaki sposób usunąć lub zapisać do oddzielnego pliku pocztę zawierającą robaka swen (więcej info o robaku swen także na stronach mks)?

Ilość rozwiązań: 1

Rozwiązanie 1:

:0B:
* 8TPbiV38OV4IdC6LBolF4DvDdBSLeESJfeSJRdxQ6AOPAABZi8fr5YleC
swen
# albo lepiej /dev/null ;)
Nadesłał 20-09-2003 Tomasz Lemiech <szpajder@staszic,waw,pl>
Zmodyfikował 23-09-2003 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>

Konwersja folderów poczty z formatu KMail na Sylpheed Claws

Problem:  W jaki sposób przekonwertować foldery poczty z formatu KMail na Sylpheed Claws?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku convert.sh:

#!/bin/sh

# konwersja folderów poczty z formatu KMail na Sylpheed Claws,
# przy załóżeniu, że znajdują się one w katalogu ~/Mail. Można to
# zmienić odpowiednio modyfikując zmienna source_dir
#
# użycie: convert.sh nazwa_folderu [licznik]
#
# licznik okresla od jakiego numeru bedziemy zaczynac numerowanie plików
# zmienna dest_dir okresla katalog docelowy programu Sylpheed UWAGA! W
# nazwach folderów nie może być spacji

source_dir="$HOME/Mail"
dest_dir="$HOME/Mail_S"
folder=$1
licznik=$2
let " licznik=( licznik>1 )? licznik:1 "

echo "Tworze katalog docelowy $dest_dir"
mkdir $dest_dir
echo "Tworze katalog docelowy $dest_dir/$folder"
mkdir $dest_dir/$folder

for plik in $source_dir/$folder/cur/*
do
 echo "konwertuje $plik na $dest_dir/$folder/$licznik"
 cp $plik $dest_dir/$folder/$licznik
 licznik=$(($licznik+1))
done

echo "zrobione"

Uwagi: użycie: convert.sh nazwa_folderu [licznik]

Nadesłał 08-05-2005 Witek Mozga <mozga@trimen,pl>


Usuwanie wszystkich procesów danego użytkownika

Problem:  W jaki sposób wylogować danego usera z systemu - zabić wszystkie jego procesy?

Ilość rozwiązań: 2

Rozwiązanie 1:

ps u -u user|awk {' if ($2~/^[0-9]+$/) print $2 '}|xargs kill -9

Uwagi: "Nieładnie jest zaczynać od SIGKILL, nie dając procesom szansy na posprzątanie po sobie. Lepiej np. SIGTERM, a dopiero po pewnym czasie opornym SIGKILL" (komentarz by Qrczak). Zobacz także 'man skill'.

Nadesłał 18-01-2004 Rafal Skoczylas <nils@secprog,org>
 


Rozwiązanie 2:

for i in `ps aux | awk '($1 == "USER") {print $2}'`; do echo $i; done 

Powyższy skrypt wypisuje procesy użytkownika USER; gdy chcemy zabić procesy użytkownika aaabbb wówczas:

for i in `ps aux | awk '($1 == "aaabbb") {print $2}'`; do kill -9 $i; done

Uwagi: Zobacz także 'man skill'.

Nadesłał 18-01-2004 Kasek <klasyk99@friko2,one,.pl>


Konwersja DOSowego pliku tekstowego na linuxowy i vice versa

Problem:  Jak się pozbyć znaku 0x0D z końca linii z plików, które były edytowane pod M$ Windows, a obecnie będą używane pod Linuksem? Jak zrobić operacje odwrotna - pliki będą tworzone pod Linuksem, a chcemy je udostępnić osobom używającym M$ Windows?

Ilość rozwiązań: 5

Rozwiązanie 1: man tr
Rozwiązanie 2: man konwert
Rozwiązanie 3: man dos2unix i man unix2dos
Rozwiązanie 4: man fromdos i man todos
Rozwiązanie 5: ściągnąć je FTP w trybie ASCII

Nadesłał 11-01-2004 Robert Jaroszuk <zim@iq,pl>
Nadesłał 11-01-2004 Mateusz Papiernik <mati@maticomp,net>
Nadesłał 11-01-2004 TRS <trs,trs@poczta,fm>
Nadesłał 12-01-2004 Jan Dubiec <jdx@slackware,pl>
Nadesłał 11-01-2004 Krzysztof Rudnik <rudnik@kki,net,pl>


Liczba Pi

Problem: Jak uzyskać liczbę Pi?

Ilość rozwiązań: 1

Rozwiązanie 1:

W języku C.

zawartość pliku liczbapi.c:

#include <stdio.h>
#include <math.h>
int main() { printf("%.10000Lg\n", 4*atanl(1.0)); }
Uwagi: Kompilacja: gcc -o liczbapi liczbapi.c -lm . Uruchomienie: ./liczbapi . Wynik: 3,14159265358979323851280895940618620443274267017841339111328125 . Wynik obliczony tą metodą daje tylko 18 cyfr znaczących po przecinku, gdyż "printf przetwarza sobie jakieś śmieci, a long double jak miało tak i ma 10 bajtów (architektura x86) na informację i z tych 10 bajtów więcej jak ok. 19 cyfr znaczących wyciągnąć się nie da." (komentarz w cudzysłowiu z dnia 28-02-2004 by Artur Gawryszczak). Więcej cyfr znaczących liczby pi możesz ściągnąć np. z tej strony: http://3.141592653589793238462643383279502884197169399375105820974944592.jp/
Znajduje się tam ok. 100 MB cyfr znaczących liczby pi - wbrew pozorom to niezbyt wiele, gdyż podobno policzono już ponad bilion. :)

Nadesłał 23-01-2004 Mateusz Papiernik <mati@maticomp,net>


Wysyłanie komunikatów poprzez mówiącą krowę

Problem: Ktoś mi wysyła komunikaty na konsolę w postaci mówiącej krowy. Jak to zrobić?

Ilość rozwiązań: 1

Rozwiązanie 1:

cowsay Fajnie, ze zajrzales na moja strone! |write userid
Wynik widziany u userid:
Message from ja@serwer on pts/4 at 02:37 ...
 ______________________________________
< Fajnie, ze zajrzales na moja strone! >
 --------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
EOF

Nadesłał 07-02-2004 Andrzej Kasperowicz <skryptylinuksa+1@gmail,com>


Zmiana właściciela i uprawnień wszystkich plików i katalogów w podanym miejscu

Problem: Jak zmienić właściciela i uprawnienia dla wszystkich plików i katalogów w podanym miejscu?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku rechown:

#!/bin/sh

while [ "$1" ]; do

DIR="$1"
OWNER="$2"
FMODE="$3"
DMODE="$4"

find "$DIR" | (
while read line; do
    echo chmoding $line
    if [ -f "$line" ]; then M=$FMODE; fi
    if [ -d "$line" ]; then M=$DMODE; fi
    chown "$OWNER" "$line"
    chmod "$M" "$line"
    done )

shift 4

done 

Uwagi: wywołanie: rechown <katalog> <wlasciciel:grupa> <uprawnienia_dla_plikow> <uprawnienia_dla_katalogow> [<katalog2> ...]

Nadesłał 16-04-2004 Maciek Grela <thermal@poczta,onet,pl>


Automatyczny update repozytoriów CVS w podanych katalogach

Problem: Jak dokonać automatycznego updatu repozytoriów CVS w podanych katalogach rekursywnie?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku updatecvs:

#!/bin/sh

PROG=`basename $0`

if [ $# -lt 1 ]; then
    echo This tool updates all CVS repositories in 
    echo given directories \(recursively\)
    echo Usage:
    echo $PROG dir1 [dir2] [dir3] ... [dirn]
    exit 0
    fi
    
while [ "$1" ]; do
    
    # Skip non-directories
    if [ ! -d "$1" ]; then shift;continue; fi
    
    # Not a CVS directory but can contain CVS repositories
    if [ ! -d "$1/CVS" ]; then
	cd "$1"
	$0 *
	if [ "$?" != "0" ]; then 
	    echo $PROG: Sub-process failed at directory $1
	    exit 1
	    fi
	cd ..
	shift;continue
	fi
    
    cd "$1"
    REPOSITORY=`cat CVS/Root`/"$1"
    echo $PROG: Updating $REPOSITORY ...
    cvs update
    cd ..

    shift
    done

exit 0

Uwagi: wywołanie: updatecvs <katalog1> <katalog2> ... updatecvs rekursywnie przeszukuje podane katalogi i wykonuje cvs update na wszystkich repozytoriach tam znalezionych.

Nadesłał 16-04-2004 Maciek Grela <thermal@poczta,onet,pl>


Skrypt do refaktoryzacji CVS

Problem: W jaki sposób zmodyfikować kod aplikacji bez dodawania nowych funkcjonalności, aby architektura systemu była lepsza?

Ilość rozwiązań: 2

Rozwiązanie 1:

Zawartość pliku repl.sh:

#!/bin/sh

# DESCR: Refactoring tool, handles CVS
# AUTHOR: Darek Cieslak, cieslakd at gazeta.pl
# URL: http://cieslakd.webpark.pl/
# USE: repl abd def | sh
#
# In ./.replfilter you can include sed commands to
# delete unwanted filenames. Example:
#
# /images\//d
#
# will ignore all files from images directory

TMP_FILE=$$
REPLFILTER=.replfilter

test -z "$1" -o -z "$2" && {
    echo give from, to strings
    exit 1;
}

sFrom="$1"
sTo="$2"

if ! test -f $REPLFILTER
then
    touch $REPLFILTER
fi

test -d CVS && isCVS=1

FILES=`find . -type f | sed -f $REPLFILTER`

fgrep --count "$sFrom" --recursive $FILES |
awk -v "sFrom=$sFrom" -v "sTo=$sTo" -v "sTmpFile=$TMP_FILE" '
BEGIN {
    FS=":"
}
!/CVS/{
    sFile = $1
    sCount = $2
    if(sCount == 0)
        next

    print "mv " s File " " sTmpFile
    print "sed \"s|" sFrom "|" sTo "|g\" <" s Tmp File " >" sFile
    print "rm " sTmpFile
}
'

find . -name "*$sFrom*" |
sed -f $REPLFILTER |
awk -v "sFrom=$sFrom" -v "sTo=$sTo" -v "isCVS=$isCVS" '

{
    sFile = $0
    sNewFile = $0
    gsub(sFrom, sTo, sNewFile);

    print "test -e " s New File " || mv " s File " " sNewFile
    if(isCVS) {
        print "cvs remove " sFile
        print "cvs add " sNewFile
    }
}

'

Uwagi: Zamienia wszystkie wystąpienia tekstu w projekcie (włącznie z podkatalogami). Niebywale proste, ale bardzo potężne narzędzie do refaktoryzacji (obsługuje także zmiany nazw plików w CVS-ie!). Użycie: repl abd def | sh

Nadesłał 04-05-2005 Darek Cieślak <cieslakd@gazeta,pl>


Rozwiązanie 2:

Zawartość pliku clone.sh:

#!/bin/sh

# DESCR: Clone existing files, handles CVS
# AUTHOR: Darek Cieslak, cieslakd at gazeta.pl
# URL: http://cieslakd.webpark.pl/
# USE: repl abd def | sh
#
# In ./.replfilter you can include sed commands to
# delete unwanted filenames. Example:
#
# /images\//d
#
# will ignore all files from images directory

TMP_FILE=$$
REPLFILTER=.replfilter

test -z "$1" -o -z "$2" && {
    echo give from, to strings
    exit 1;
}

if ! test -f $REPLFILTER
then
    touch $REPLFILTER
fi

sFrom="$1"
sTo="$2"

FILES=*$sFrom*

find . -name "*$sFrom*" |
sed -f $REPLFILTER |
awk -v "sFrom=$sFrom" -v "sTo=$sTo" -v "isCVS=$isCVS" '

{
    sFile = $0
    sNewFile = $0
    gsub(sFrom, sTo, sNewFile);

    print "test -f " s New File " || "\
        "sed \"s/" sFrom "/" sTo "/g\" " s File " > " sNewFile
}

'

Uwagi: Podobne do Rozwiązania 1, ale nie zamienia plików tylko je klonuje. Użycie: repl abd def | sh

Nadesłał 04-05-2005 Darek Cieślak <cieslakd@gazeta,pl>


Konwersja daty z języka angielskiego na polski

Problem: Jak przekonwertować datę z języka angielskiego na polski?

Ilość rozwiązań: 2

Rozwiązanie 1:

if [ $# -ge '1' ]
then


if [ $1 = "-e" ]

then
	echo `date`

elif [ $1 = "-p" ]

then

	set `date`

case $1 in
	Mon)b="Poniedzialek";;
	Tue)b="Wtorek";;
	Wed)b="Sroda";;
	Thu)b="Czwartek";;
	Fri)b="Piatek";;
	Sat)b="Sobota";;
	Sun)b="Niedziela";;
esac

case $2 in 
	Jan)a="Styczen";;
	Feb)a="Luty";;
	Mar)a="Marzec";;
	Apr)a="Kwiecien";;
	May)a="Maj";;
	Jun)a="Czerwiec";;
	Jul)a="Lipiec";;
	Sep)a="Sierpien";;
	Aug)a="Wrzesien";;
	Oct)a="Pazdziernik";;
	Nov)a="Listopad";;
	Dec)a="Grudzien";;
esac
echo "$b $a $3 $4 $5 $6";
fi
fi

Uwagi: skrypt z linii poleceń pobiera 1 parametr: -e wyświetla datę bez zmian, -p konwertuje datę na polski. "Jak ktoś ma zwalone locale, a chce mieć po polsku to jest to najprostsze rozwiązanie."

Nadesłał 27-04-2004 Jakub Tyszko <kuba@lbl,pl>


Rozwiązanie 2:

date | sed -e 's/Mon/Poniedzialek/g; s/Tue/Wtorek/g; s/Wed/Sroda/g;
s/Thu/Czwartek/g; s/Fri/Piatek/g; s/Sat/Sobota/g; s/Sun/Niedziela/g;
s/Jan/Styczen/g; s/Feb/Luty/g; s/Mar/Marzec/g; s/Apr/Kwiecien/g;
s/May/Maj/g; s/Jun/Czerwiec/g; s/Jul/Lipiec/g; s/Sep/Sierpien/g;
s/Aug/Wrzesien/g; s/Oct/Pazdziernik/g; s/Nov/Listopad/g;
s/Dec/Grudzien/g'

Uwagi: W odróżnieniu od rozwiązania 1 datę zamienia bezwarunkowo i bez parametrów przy starcie.

Nadesłał 07-05-2004 Jakub Tyszko <kuba@lbl,pl>


Skrypt do przypominania np. o zmianie taśm do backupu

Problem: Jak zrobić skrypt przypominacz do przypominania o różnych rzeczach?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku tasmy_zmiana:

#!/bin/bash
# Informacja o zmianie taśm uruchamiana z CRONA

DZIEN=`date +%u`

# Kazdy piatek
if [ "$DZIEN" == "5" ]
then
echo "Zmien tasmy: ..." | mail -s "Zmiana tasm" adres@domena.pl
fi

# Ostatnie środy miesiąca - info: Paweł Gancarz
[ $(date -d '+ 1 week' +%-m) -ne $(date +%-m) ] && \
[ $(date +%A) == "sroda" ] && echo "Zmien tasmy: ..." | mail -s "Zmiana tasm" adres@domena.pl
# lub [ $(date +%w) -eq 3 ]  - aby było go łatwiej przenieść na inne maszyny

Uwagi: Skrypt służy do przypominania o zmianie taśm do backupu. Najlepiej uruchamiać go z crona. Do crontab wpisujemy na przykład: 01 09 * * * /home/user/tasmy_zmiana co spowoduje wykonanie skryptu każdego dnia z rana minutę po dziewiątej.

Nadesłał 27-04-2005 Marcin Wasilewski <marcinwasilewski@poczta,onet,pl>
Zmodyfikował 27-04-2005 Paweł Gancarz <pgancarz@o2,pl>


Synchronizacja katalogów FTP w jedną stronę

Problem:  W jaki sposób zsynchronizować katalogi FTP w jedną stronę?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku ftpsync.sh:

#!/bin/sh

# DESCR: FTP syncing script
# AUTHOR: Dariusz Cieślak, cieslakd at gazeta.pl
# URL: http://cieslakd.webpark.pl/
#
# USAGE:
#
#   ftpsync remote_dir stamp_file [files...] | pftp hostname
#   touch stamp_file
#
# I know this is simple, but allows high flexibility
# A this time allows only two-level hierarchy od directories

REMOTE_DIR="$1"
STAMP="$2"

test -z "$STAMP" && {
    echo $0 remote_dir stamp_file
    exit 1
}
test -f $STAMP || touch $STAMP -d '1977-01-01'

find . -follow -newer $STAMP -a -type d |\
awk -vREMOTE_DIR="$REMOTE_DIR" '
BEGIN {
    FS = "/"
    print "mkdir " REMOTE_DIR
    print "cd " REMOTE_DIR
}
$0 != "." {
    print "mkdir " $0
}

'

find . -follow -newer $STAMP -a -type f |\
awk -vREMOTE_DIR="$REMOTE_DIR" '
BEGIN {
    FS = "/"
}
!/\.swp/ {
    if(NF > 2) {
        if($2 != DIR) {
            print "cd " $2
            print "lcd " $2
            DIR = $2
        }
        file=$3
    } else {
        if(DIR) {
            print "cd .."
            print "lcd .."
            DIR = ""
        }
        file=$2
    }
    print "put " file
    if(/cgi$/) {
        print "chmod 0755 " file
    }
}

'

Uwagi: Użycie: ftpsync remote_dir stamp_file [files...] | pftp hostname touch stamp_file

Nadesłał 04-05-2005 Darek Cieślak <cieslakd@gazeta,pl>


Skrypt powiadamiający o zdarzeniu (np. o nadchodzącej poczcie) poprzez włączenie "śniegu" na ekran

Problem:  W jaki sposób stworzyć skrypt powiadamiający o zdarzeniu (np. nadchodzącej poczcie) poprzez włączenie xsnow "śniegu" lub efektu dźwiękowego?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku powiadom.sh:

#!/bin/sh

# Script that notifies about incoming mail (or any other event). It
# uses xsnow (and mpg123), but can use any other XWindow toys and
# sound effects
#
# skrypt powiadamiający o jakimś zdarzeniu (np. przyjściu poczty) 
# jeśli wywołany bez argumentów to włącza program xsnow
# z argumentem "stop" usuwa xsnow
#
# zamiast xsnow można użyć innych "przeszkadzajek"
# URL: http://cieslakd.webpark.pl/

PROGRAM=xsnow 
PATH=$PATH:/usr/X11R6/bin

if test "$1" = stop
then
    killall $PROGRAM > /dev/null 2> /dev/null
    exit 0
fi

if ! ps x | grep $PROGRAM | awk 'END{exit NR < 2}'
then
    MP3=/usr/local/sounds/zaniemoglo.mp3
    mpg123 $MP3 2>/dev/null >/dev/null &
    export DISPLAY=:0.0
    $PROGRAM &
fi

cat > /dev/null

exit 0

Uwagi: skrypt powiadamiający o jakimś zdarzeniu (np. przyjściu poczty); jeśli wywołany bez argumentów to włącza program xsnow z argumentem "stop" usuwa xsnow.

Nadesłał 04-05-2005 Darek Cieślak <cieslakd@gazeta,pl>


Skrypt pokazujący pogodę na dzień jutrzejszy

Problem:  W jaki sposób wykonać skrypt pokazujący pogodę na dzień jutrzejszy?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku pogoda.sh:

#!/bin/sh
# URL: http://cieslakd.webpark.pl/

DATE=`date -d tomorrow +%Y.%m.%d`
FILE=~/input/pogoda.png

export DISPLAY=:0.0

URL=http://w.wp.pl/p/pogoda/i/general/country/POL/forecast


wget\
  -q $URL/$DATE.png\
  -O $FILE\
  || exit 1


xli -title "Pogoda na jutro ($DATE)"\
    -quiet -center $FILE

Nadesłał 04-05-2005 Darek Cieślak <cieslakd@gazeta,pl>


Skrypt pokazujący na ekranie losowy komiks z http://userfriendly.pl

Problem:  W jaki sposób wykonać skrypt pokazujący na ekranie losowy komiks z http://userfriendly.pl ?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku userfriendly.sh:

#!/bin/sh
# URL: http://cieslakd.webpark.pl/

export DISPLAY=:0.0

ping -c 1 userfriendly.pl > /dev/null || exit 1

cd /tmp
test -d uf && rm -rf uf
mkdir uf
cd uf

wget -q -A gif -nd -r -l1 http://userfriendly.pl/index.php?data=random

/usr/X11R6/bin/xli -quiet [0-9]*.gif

Nadesłał 04-05-2005 Darek Cieślak <cieslakd@gazeta,pl>


Skrypt przekazujący na stdout wylosowany argument

Problem:  W jaki sposób skierować na standardowe wyjście wylosowany argument?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku rand-arg.awk:

#!/usr/bin/awk -f

# DESCR: returns on stdout random argument
# AUTHOR: Darek Cieslak (cieslakd at wp.pl)
# URL: http://cieslakd.webpark.pl/

BEGIN{
    srand()
    nr = ARGC
    size = ARGC
    r = int(rand() * (size - 1)) + 1
    print ARGV[r]
    exit(0)
}

Uwagi: Wyrzuca na stdout wylosowany argument. Przykładowe zastosowania: losowe tła. ;)

Nadesłał 04-05-2005 Darek Cieślak <cieslakd@gazeta,pl>


Skrypt sprawdzający styl programu w Javie

Problem:  W jaki sposób sprawdzić styl programu w Javie?

Ilość rozwiązań: 1

Rozwiązanie 1:

Zawartość pliku javaStyle.sh:

#!/bin/sh
# URL: http://cieslakd.webpark.pl/

awk '

/if\(/ || /while\(/ || /for\(/ {
    print FILENAME ":" FNR ": add space"
}
/^\t*{/ {
    print FILENAME ":" FNR ": move { to upper line"
}
/\){/ {
    print FILENAME ":" FNR ": add space between ) and {"
}
/^\t*if.*[^{]$/ {
    print FILENAME ":" FNR ": add { ... }"
}
/^\t*while.*[^{]$/ {
    print FILENAME ":" FNR ": add { ... }"
}
/^\t*for.*[^{]$/ {
    print FILENAME ":" FNR ": add { ... }"
}
/printStackTrace\(\)/ {
    print FILENAME ":" FNR ": redirect logs to log4j"
}


' *.java

Nadesłał 04-05-2005 Darek Cieślak <cieslakd@gazeta,pl>


Automatyczne kontrolowanie czasu zalogowania i blokowanie logowania użytkowników

Problem:  W jaki sposób kontrolować czas zalogowania użytkowników i nie dopuszczać do ich ponownego zalogowania, jeśli się sami nie wylogują w ciągu określonego czasu?

Ilość rozwiązań: 1

Rozwiązanie 1:

#!/bin/sh
#funkcja sprawdzajaca czy czas nie zostal przekroczony
function  sprawdz () {
        # jesli pozostala tylko jedna (tak naprawde dwie :) ) minuta
       if [ `expr $wyl - $czas ` -eq 2 ];then
		#wysylanie uzytkownikowi komunikatu o wylogowaniu go za 1 minute, komunikat umiesczony w pliku o nazwie "komunikat" 
        	mesg y;
		#wyswietleenie komunikatu znajdujacego sie  w pliku komunikat(trzeba go sobie utworzyc samemu)
		write $i < komunikat ;
        	#zeby uzytownik nie mogl do nas odpisac
		mesg n;
	fi ;
	# jesli czas uzytkownika minal zostaje on wylogowany z systemu
        if [ `expr $wyl - $czas ` -le 0  ];then 
            #    echo "Wylogowuje uzytkownikow"
               skill -STOP $i;
               skill -9 $i;
		#blokujemy uzytkownika do konca dnia
		passwd -l $i;
		#po polnocy jego konto zotaje znow odblokowane
		echo "passwd -u $i" >> odblok
		at -f odblok 12:00am 
		at -f aktual 12:00am
        	
	fi ;
			}
#plik czyszczacy co noc liste zablokowanych uzytkownikow
touch aktual
# polecenia usuwajace plik odblokuj
echo "#!/bin/sh" > aktual;

echo "rm odblok" >> aktual;
while [ 1 ]
do
#plik zawierajacy uzytkownikow do oblokowwania
touch odblok 
#funkcja sprawdzajaca czy czas nie zostal przekroczony
wyl=$1; # czas po ktorym wszyscy zwykli uzytkownicy wylogowani
uzy=`users`
for i in $uzy 
do  
uid=`id $i | awk '{print $1}' | cut -f 1 -d "("`;
	#sprawdzam czy superuzytkownik, jesli tak dalej pomijam go
	if [ "$uid"  != "uid=0" ] ; then
	#obecna godzina, minuta i strefa
	h=`date "+ %I"`
	m=`date "+ %M"`
	obczas=`expr $h \* 60 + $m`
	obstr=`date "+%p"`
	if [ "$obstr" = "PM" ]; then 
	#dodajemy 12 h dla godzin popoludniowych 
	obczas=`expr $obczas + 720`
	fi ;
        # jesli jest godizna 12 odejmujemy 12 h
	if [ $h -eq 12 ]; then 
	obczas=`expr $obczas - 720`
	fi ;
	#godzina i minuta logowania dla konkretnego uzytkownika
	hl=`w | grep $i | awk '{print $4}' | cut -f1 -d":"`
	ml=`w | grep $i | awk '{print $4}' | cut -f2 -d":" | cut -c 1,2`
	logstr=`w | grep $i | awk '{print $4}' | cut -f2 -d":" | cut -c 3,4`
	for ((j=1;j <= "`echo $ml | wc -w`";j++)); 
		do 
		# pobieram kolejne wartosci czasow zaologwania danego uzytkownika na roznych terminalach 
		khl=`echo $hl | cut -f$j -d" "`
		kml=`echo $ml | cut -f$j -d" "` 
		kstr=`echo $logstr | cut -f$j -d" "`
		oblog=`expr  $khl \* 60 + $kml`
		#jesli nastapila zmina dnia 
		if [ "$kstr" = "pm" ]; then 
		if [ "$obstr" = "AM" ];then 
		#dodaje minuty z dnia poprzedniego
		czas=`expr 720 - $oblog + $obczas` ;
		#sprawdzamy czy czas uztkownika nie dobiegl konca
		sprawdz ;
		fi ;
		fi ; 
		if [ "$kstr" = "pm" ]; then
        	#dodajemy 12 h dla godzin popoludniowych 
        	oblog=`expr $oblog +  720`
        	fi ;
        	# jesli jest godzina 12 odejmujemy 12 h
        	if [ $khl -eq 12 ]; then
        	oblog=`expr $oblog - 720`
        	fi ;
		czas=`expr $obczas - $oblog`
		sprawdz ;
		done ; 
	fi ;    
done
#sprawdzanie co 55 sekund
sleep 55 ;
done  

Uwagi: Skrypt uruchamiany przez superużytkownika z odpowiednim parametrem kontroluje czas zalogowania pozostałych użytkowników. Parametr ten podawany jest w minutach, 2 minuty przed zakończeniem czasu użytkownik informowany jest o tym że zostanie wylogowany, jeśli zrobi to sam, będzie mógł się normalnie ponownie zalogować, jeśli nie, zostanie usunięty, a jego konto zablokowane do końca dnia. Tak to powinno działać, u mnie na RH 7 działa bezproblemowo, mam nadzieje, że u innych również zadziała. Skrypt powinien działać ciągle :) (wiem może głupia i niepotrzebna uwaga, ale chciałbym, żeby wszystko było jasne). Jedynym plikiem (poza plikiem w którym umieścimy powyższy skrypt) jaki należy utworzyć jest plik komunikat, zawierający treść komunikatu, który ma się pojawić na terminalu użytkownika 2 minuty przed wylogowaniem. Proszę w czasie logowania informować użytkownika na jaki czas zostaje zalogowany, żeby później nie stawiać go przed faktem dokonanym.

Nadesłał 05-05-2005 Krzysztof Szkutak <dzivny@o2,pl>


Łączenie się z internetem spod konsoli tekstowej

Problem:  Jak połączyć się z internetem spod konsoli tekstowej?

Ilość rozwiązań: 1

Rozwiązanie 1:

Wykorzystamy trzy skrypty, które należy umieścić w katalogu /etc/ppp:

Poniżej można zobaczyć przykładowe skrypty przystosowane do połączeń z numerem dostępowym TP S.A.

ppp-on

#!/bin/sh
TELEPHONE=0202122
ACCOUNT=ppp
PASSWORD=ppp
export TELEPHONE ACCOUNT PASSWORD
# zmienne są eksportowane, aby mógł
# z nich korzystać ppp-on-dialer
DIALER_SCRIPT=/etc/ppp/ppp-on-dialer
# pełna ścieżka do tego skryptu
exec /usr/sbin/pppd crtscts /dev/modem 115200 \
lock modem defaultroute \
connect $DIALER_SCRIPT
# opcje przekazywane pppd podczas jego startowania

ppp-off

#!/bin/sh

if [ "$1" = "" ]; then
        DEVICE=ppp0
else
        DEVICE=$1
fi

if [ -r /var/run/$DEVICE.pid ]; then
        kill -INT `cat /var/run/$DEVICE.pid`

        if [ ! "$?" = "0" ]; then
                rm -f /var/run/$DEVICE.pid
                echo "ERROR: Removed stale pid file"
                exit 1
        fi


        echo "PPP link to $DEVICE terminated."
        exit 0
fi

echo "ERROR: PPP link is not active on $DEVICE"
exit 1

ppp-on-dialer

#!/bin/sh
exec chat -v \
        TIMEOUT 3 \
        ABORT   '\nBUSY\r'\
        ABORT   '\nNO ANSWER\r'\
        ABORT   '\nRINGING\r\n\r\nRINGING\r'\
        '' \rAT \
        'OK-+++\c-OK'         ATZ \
        TIMEOUT 30 \
        OK ATDT$TELEPHONE \
        CONNECT '' \
        ogin:--ogin: $ACCOUNT \
        assword: $PASSWORD

Uwagi:

"Należy skryptom nadać atrybut wykonywalności poleceniem:
chmod a+x /etc/ppp/ppp-*

ppp-on

Jeśli korzystamy z innego dostawcy usług internetowych, należy w polach TELEPHONE, ACCOUNT i PASSWORD, podać odpowiednie dane.
/usr/sbin/pppd jest to ścieżka do demona pppd. Jeśli u nas znajduje się on w innym katalogu, należy podać poprawną ścieżkę.
/dev/modem jest ścieżką do pliku reprezentującego port, na którym zainstalowany jest nasz modem. Jeśli mamy modem na porcie COM1, to poleceniem
ln -s /dev/ttyS0 /dev/modem
utworzymy dowiązanie symboliczne do pliku reprezentującego ten port. Analogicznie dla portu COM2 jest to ttyS1, COM3 - ttyS2, COM4 - ttyS3, itd. Jeśli nie wiemy, na jakim porcie jest nasz modem, należy próbować również cua0, cua1, cua2, cua3, ttyI0, ttyI1, ttyI2, ttyI3.
115200 oznacza prędkość, z jaką modem będzie komunikował się z komputerem poprzez port. W przypadku mniejszych możliwości należy ustawić ją na 57600 lub 38400.

ppp-on-dialer

W przypadku TPSA ogin powinniśmy zastąpić słowami ername. U inny operatorów ta wartość może być różna, warto się dowiedzieć, gdy powyższe sekwencje znaków nie dają rezultatu.
ATZ - komenda inicjalizująca nasz modem. W zależności od modemu należy podać tutaj właściwą komendę. W prosty sposób można poznać, że dana komenda jest zła, gdy po uruchomieniu skryptu ppp-on nasz modem nie zareaguje. W przypadku gdy ATZ nie działa możesz spróbować polecenia ATH0.
ATDT - komenda dzwonienia. Gdy ATDT nie zadziała, musisz dowiedzieć się jaka jest właściwa komenda dla twojego modemu i wpisać ją.
Czasem, przy połączeniach z TPSA, może się zdarzyć, że nie będziemy mogli zrealizować połączenia. W takim przypadku można zmienić opcję TIMEOUT 30 na TIMEOUT 60.
W przypadku problemów z logowaniem należy zmienić ogin:--ogin: na Username: oraz zamienić assword: na Password: .

Łączymy się z internetem wydając polecenie:
/etc/ppp/ppp-on

Po kilkunastu sekundach, gdy  nawiążemy połączenie możemy sprawdzić czy wszystko gra poleceniem:
/sbin/ifconfig

Rozłączamy się poleceniem:
/etc/ppp/ppp-off

Autentyfikacja PAP

W wielu miastach TP S.A. wymaga przy połączeniach autentyfikacji PAP. Edytujemy plik /etc/ppp/pap-secrets i dopisujemy:
ppp * ppp
Następnie plik /etc/ppp/options i dodajemy:
+pap
user pap

Ustawienie DNS'ów

Nazwy domen będą tłumaczone na numery IP jeśli w pliku /etc/resolv.conf wpiszemy:

search
nameserver 194.204.159.1
nameserver 194.204.152.34    "

Źródło: linux.gnu.pl i linux.sky.pl <Artur Pęczak arturoza@send,pl 13-10-2000>
Dodano do niniejszej strony dnia 17-09-2003


Podział łącza na kilku użytkowników z możliwością przypisania im różnych przepustowości

Problem: Jak podzielić łącze na kilku użytkowników z możliwością przypisania im różnych przepustowości?

Ilość rozwiązań: 1

Rozwiązanie 1:

ISP Bandwidth Shaper:

Zawartość pliku rc.an_prio:

#!/bin/bash

#
# Copyright (c) 2005 Lukasz Dembinski
# mailto: <dembol@nasa.com.pl>
# ver. 1.0
#
# Na podstawie:
# http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm
#

# predkosc download naszego lacza
DOWNLINK_SPEED_ISP="512kbit"

# predkosc upload naszego lacza
UPLINK_SPEED_ISP="256kbit"

# predkosc upload naszego lacza dla portow nieinteraktywnych
UPLINK_SPEED_ISP_LOW="100kbit"


# predkosc download naszego lacza przypisana userom
DOWNLINK_SPEED_ALL="512kbit"

# predkosc upload z naszego lacza przypisana userom
UPLINK_SPEED_ALL="256kbit"

# ip,predkosc ip,predkosc"
UPLINK_IP="192.168.0.10,128kbit 192.168.0.11,128kbit 192.168.0.0/24,64kbit" 	

# predkosc upload sieci LAN
UPLINK_SPEED_LAN="100mbit"

# "ip,predkosc,ceil,priorytet ip,predkosc,ceil,priorytet"
# Lepiej nie ustawiac sumy predkosci na wartosc wyzsza niz DOWNLINK_SPEED_ALL
# Dokumentacja tak komentuje taka sytuacje: 
#
# Q: What if sum of child rates is greater than parent rate ?
# A: Then interesting things can happen

DOWNLINK_IP="192.168.0.10,128kbit,512kbit,1 192.168.0.11,256kbit,512kbit,1 192.168.0.0/24,64kbit,128kbit,2" 

# predkosc download sieci LAN
DOWNLINK_SPEED_LAN="100mbit"

# porty interaktywne
INTERACT_PORTS="20 21 22 25 110" 

# hosty interaktywne
INTERACT_HOSTS="" 

# predkosc download dla portow - "port,predkosc port,predkosc"
PORT_SPEED="80,384kbit" 

# adres naszej sieci lokalnej
LAN_IP=192.168.0.0/24

# interfejs na "swiat"
IF_WORLD="eth0"  

# interfejs lokalny
IF_LAN="eth1"    


# ----- czyscimy wszystko -----

tc qdisc del dev $IF_WORLD root 2> /dev/null
tc qdisc del dev $IF_LAN   root 2> /dev/null
tc qdisc del dev $IF_WORLD ingress 2> /dev/null
tc qdisc del dev $IF_LAN   ingress 2> /dev/null


# ------ output IF_WORLD ----------

DEV=$IF_WORLD

echo
echo "Output dev" $DEV

tc qdisc add dev $DEV root handle 1: htb default 20

tc class add dev $DEV parent 1: classid 1:1 htb rate ${UPLINK_SPEED_ISP} \
   burst 10k

tc class add dev $DEV parent 1:1 classid 1:10 htb rate ${UPLINK_SPEED_ISP} \
  burst 10k prio 1

tc class add dev $DEV parent 1:1 classid 1:20 htb rate ${UPLINK_SPEED_ISP_LOW} \
   burst 10k prio 2

tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10

for port in $INTERACT_PORTS
do
    echo 'Setting port' $port 'as interactive';

    tc filter add dev $DEV parent 1: protocol ip prio 1 u32 \
    match ip sport ${port} 0xffff flowid 1:10

    tc filter add dev $DEV parent 1: protocol ip prio 1 u32 \
    match ip dport ${port} 0xffff flowid 1:10
done

echo 'Setting TOS 0x10 as interactive';

tc filter add dev $DEV parent 1:0 protocol ip prio 3 u32 \
      match ip tos 0x10 0xff  flowid 1:10

echo 'Setting ICMP as interactive';

# -- icmp protocol --
tc filter add dev $DEV parent 1:0 protocol ip prio 3 u32 \
        match ip protocol 1 0xff flowid 1:10
    
tc filter add dev $DEV parent 1: protocol ip prio 10 u32 \
   match ip protocol 6 0xff \
   match u8 0x05 0x0f at 0 \
   match u16 0x0000 0xffc0 at 2 \
   match u8 0x10 0xff at 33 \
   flowid 1:10

echo 'Setting other ports as mass ports';

k=1
for host in $INTERACT_HOSTS
do
    echo 'Setting host' $host 'as interactive';
    
    tc filter add dev $DEV parent 1: protocol ip prio 10 u32 \
    match ip dst $host flowid 1:10
done


# ------ input IF_WORLD ----------

echo
echo "Input dev" $DEV

tc qdisc add dev $DEV handle ffff: ingress

k=1
for port in $PORT_SPEED
do
    p=1;
    parametry=`echo $port | sed "y/,/ /"`
    for param in $parametry
    do
	params[$p]=$param;
	((p++))
    done

    echo 'Setting port' ${params[1]} 'downlink speed to' ${params[2]}

    tc filter add dev $DEV parent ffff: protocol ip prio 1 u32 match ip \
    sport ${params[1]} 0xffff police rate ${params[2]} burst 10k drop flowid :${k}

    ((k++))
done

echo 'Setting other ports downlink speed to' ${DOWNLINK_SPEED_ISP}

tc filter add dev $DEV parent ffff: protocol ip prio 2 u32 match ip \
src 0.0.0.0 police rate ${DOWNLINK_SPEED_ISP} burst 6k drop flowid :${k}


# ------ output IF_LAN ----------

DEV=$IF_LAN

echo
echo "Output dev" $DEV

tc qdisc add dev $DEV root handle 2: htb default 2

echo 'Setting LAN' $LAN_IP 'downlink speed to' ${DOWNLINK_SPEED_LAN}

tc class add dev $DEV parent 2: classid 2:2 htb rate ${DOWNLINK_SPEED_ALL} \
   burst 10k prio 1

tc class add dev $DEV parent 2: classid 2:1 htb rate ${DOWNLINK_SPEED_LAN} \
   burst 20k prio 2

tc qdisc add dev $DEV parent 2:1 handle 3: sfq perturb 10

tc filter add dev $DEV parent 2: protocol ip prio 1 u32 match \
    ip src ${LAN_IP} flowid 2:1

tc filter add dev $DEV parent 2: protocol ip prio 1 u32 \
    match ip protocol 1 0xff flowid 2:1


k=2
for ip in $DOWNLINK_IP 
do
    p=1;
    parametry=`echo $ip | sed "y/,/ /"`
    for param in $parametry
    do
	params[$p]=$param;
	((p++))
    done

    echo 'Setting' ${params[1]} 'downlink speed to' ${params[2]}/${params[3]} 'with prio' ${params[4]};

    tc class add dev $DEV parent 2:2 classid 2:${k}0 htb rate ${params[2]} \
	 burst 6k prio ${params[4]} ceil ${params[3]}

    tc qdisc add dev $DEV parent 2:${k}0 handle ${k}0: sfq perturb 10

    tc filter add dev $DEV parent 2: protocol ip prio 2 u32 match \
    ip dst ${params[1]} flowid 2:${k}0

    ((k++))
done


# ------ input IF_LAN ----------

echo
echo "Input dev" $DEV

tc qdisc add dev $DEV handle ffff: ingress

echo 'Setting LAN' $LAN_IP 'uplink speed to' ${UPLINK_SPEED_LAN}

tc filter add dev $DEV parent ffff: protocol ip prio 1 u32 match ip \
dst ${LAN_IP} police rate ${UPLINK_SPEED_LAN} burst 20k drop flowid :1

tc filter add dev $DEV parent ffff: protocol ip prio 1 u32 \
match ip protocol 1 0xff police rate ${UPLINK_SPEED_LAN} burst 20k drop flowid :1

k=2
for ip in $UPLINK_IP 
do
    p=1;
    parametry=`echo $ip | sed "y/,/ /"`
    for param in $parametry
    do
	params[$p]=$param;
	((p++))
    done

    echo 'Setting' ${params[1]} 'uplink speed to' ${params[2]}

    tc filter add dev $DEV parent ffff: protocol ip prio 2 u32 match ip \
      src ${params[1]} police rate ${params[2]} burst 10k drop flowid :${k}

    ((k++))
done
 

Uwagi: Jest to skrypt umożliwiający szybkie skonfigurowanie podziału łącza na kilku użytkowników z możliwością przypisania im różnych przepustowości. Każdemu użytkownikowi można określić inną prędkość downloadu i uploadu, maksymalną prędkość downloadu (gdy łącze jest niewykorzystane) oraz priorytet dla schedulera. Dodatkowo skrypt konfiguruje QoS dla pakietów wychodzących i umożliwia podanie portów interaktywnych, które będą priorytetyzowane w celu minimalizacji opóźnień. Do poprawnego działania potrzebne jest tc i odpowiednie skonfigurowanie jądra z obslugą QoS.
Oprócz powyższego miejsca skrypt można też ściągnąć stąd. Zapraszam wszystkich do testowania i poprawiania skryptu, jako że na pewno idealny nie jest. :)

Zasada działania

Skrypt opiera się na kolejkach HTB i INGRESS. Kształtowanie ruchu wejściowego użytkowników oraz narzucanie polityki dla ich ruchu wyjściowego odbywa się na interfejscie IF_LAN. To tam działa HTB, który kształtuje szybkości downloadu dla poszczególnych userów, oraz INGRESS, który ogranicza ich prędkości upload. Pakiety skierowane bezpośrednio na adres należący do LAN-u są obsługiwane oczywiście z maksymalną prędkością. Priorytetyzowanie pakietów odbywa się na interfejsie IF_WORLD. Skrypt pozwala na podanie numerów portów oraz IP hostów wymagających ruchu interaktywnego. Są one wtedy obsługiwane z najwyższym priorytetem. Dodatkowo, priorytetyzowane są pakiety IP z TOS równym 0x10 (najmniejsze opóźnienie)

Konfiguracja

Konfiguracja sprowadza się do wpisania odpowiednich parametrów Twojej sieci i łącza. Oto one: No i to wszystko! Wystarczy skonfigurować i odpalić. Myślę że bez większych problemów każdemu powinno działać

Przykładowy wydruk ze skryptu:

$ ./rc.an_prio
Output dev eth0
Setting port 20 as interactive
Setting port 21 as interactive
Setting port 22 as interactive
Setting port 25 as interactive
Setting port 110 as interactive
Setting TOS 0x10 as interactive
Setting ICMP as interactive
Setting other ports as mass ports

Input dev eth0
Setting port 80 downlink speed to 384kbit
Setting other ports downlink speed to 512kbit

Output dev eth1
Setting LAN 192.168.0.0/24 downlink speed to 100mbit
Setting 192.168.0.10 downlink speed to 128kbit/512kbit with prio 1
Setting 192.168.0.11 downlink speed to 256kbit/512kbit with prio 1
Setting 192.168.0.0/24 downlink speed to 64kbit/128kbit with prio 2

Input dev eth1
Setting LAN 192.168.0.0/24 uplink speed to 100mbit
Setting 192.168.0.10 uplink speed to 128kbit
Setting 192.168.0.11 uplink speed to 128kbit
Setting 192.168.0.0/24 uplink speed to 64kbit

Nadesłał 14-05-2004 Łukasz Dembiński <dembol@nasa,com,pl>


Kierowanie ruchem w sieci pod linuksem

Problem: Pod linuksem był uruchomiony program MLDonkey, który (jak wiadomo) ściąga z sieci różne rzeczy. Problem polegał na tym, że zapychał on całe pasmo "biednego" SDI i w trakcie "intensywnego" ściągania przeglądanie stron WWW było bardzo wolne. Chciałem wykorzystać specjalne mechanizmy kierowania danymi na zasadzie priorytetów - tzn. że jak komputer ładuje stronę WWW to MLDonkey ma w tym czasie "wyhamować". Ostatecznie po wielu próbach okazało się, że kierowanie ruchem w ten sposób nie daje dobrych rezultatów.
Chodziło chyba o to, że gdy MLDonkey otwierał, powiedzmy 150 połączeń to wtedy każde jedno otwarte połączenie przeglądarki WWW nie dawało tym 150 połączeniom MLDonkeyowym rady.

Ilość rozwiązań: 1

Rozwiązanie 1:

Gdy już byłem kompletnie załamany - wpadł mi do głowy pomysł i już po dwóch dniach nauki składni BASH i pomocy dobrych ludzi z grupy dyskusyjnej udało mi się napisać prosty skrypt, który robi cos takiego:

  1. sprawdza ile jest przesłanych danych pomiędzy Internetem a komputerem za maskarada.
  2. czeka sekundę
  3. sprawdza jeszcze raz to, co w punkcie 1.
  4. jeśli się okaże, że w ciągu tej sekundy przeszło więcej niż np. 0,5KB wtedy blokuje porty MLDonkeya (jeśli były otwarte)
  5. jeśli jest mniej niż 0,5KB - wtedy otwiera te porty, jeśli były zamknięte.

w ten oto sposób, gdy przeglądam strony WWW lub robię cos innego w sieci, to MLDonkey ma blokadę. Jeśli nic nie robię to MLDonkey nie ma ograniczeń. Działa to w miarę sprawnie i nie obciąża znacząco serwera.

Aha - jeśli nie macie pojęcia o czym pisze (kilka miechów temu [ten tekst był pisany w 2002 r.] też bym kompletnie nie miał pojęcia o tym, co napisałem powyżej) to dodam tylko, ze to rozwiązanie działa na Linuxie, który robi u mnie za serwer. Dodam jeszcze, że nie mam pojęcia jak coś takiego zrobić na Windowsie, więc nie pytajcie o to (Windowsa używam na moim głównym komputerze, linux tylko dostarcza Internet poprzez SDI, no i na nim działa MLDonkey - odmiana eDonkey'a).

# skrypt glowny , josh 22/08/02 12:14
echo "1" > run

Z=`iptables -L FORWARD -v -x -n |awk '{print $2}' |tail -n1`

while [ `cat run` = 1 ] ; do

Z1=$Z

sleep 1

Z2=`iptables -L FORWARD -v -x -n |awk '{print $2}' |tail -n1`

Z=$Z2

Z3=$((Z2-$Z1))

echo $Z3

if [ $Z3 -gt 500 ] ; then

if [ `cat state` = 0 ] ; then

./mlstop

echo "mlstop"

echo "1" > state

fi

else

if [ `cat state` = 1 ] ; then

./mlstart

echo "mlstart"

echo "0" > state

fi

fi

done

# skrypty: mlstart i mlstop , josh 22/08/02 12:15
./MLSTART:
iptables -t filter -D INPUT -p tcp --destination-port 4662 -j REJECT
iptables -t filter -D INPUT -p tcp --source-port 4662 -j REJECT
iptables -t filter -D OUTPUT -p tcp --destination-port 4662 -j REJECT
iptables -t filter -D OUTPUT -p tcp --source-port 4662 -j REJECT

iptables -t filter -D INPUT -p tcp --destination-port 4661 -j REJECT
iptables -t filter -D INPUT -p tcp --source-port 4661 -j REJECT
iptables -t filter -D OUTPUT -p tcp --destination-port 4661 -j REJECT
iptables -t filter -D OUTPUT -p tcp --source-port 4661 -j REJECT


./MLSTOP
iptables -t filter -A INPUT -p tcp --destination-port 4662 -j REJECT
iptables -t filter -A INPUT -p tcp --source-port 4662 -j REJECT
iptables -t filter -A OUTPUT -p tcp --destination-port 4662 -j REJECT
iptables -t filter -A OUTPUT -p tcp --source-port 4662 -j REJECT

iptables -t filter -A INPUT -p tcp --destination-port 4661 -j REJECT
iptables -t filter -A INPUT -p tcp --source-port 4661 -j REJECT
iptables -t filter -A OUTPUT -p tcp --destination-port 4661 -j REJECT
iptables -t filter -A OUTPUT -p tcp --source-port 4661 -j REJECT

Uwagi: Skrypt zakłada plik o nazwie ./run i wpisuje w nim "1". Jest to warunek do powtarzania się pętli czyli całego programu. Jeśli chcesz zatrzymać program musisz z np. innej konsoli wpisać do pliku ./run "0" - wtedy program się zatrzyma. Następnie "Z=bla bla bla" to punkt 1. wg powyższego opisu, a "Z2=bla bla bla" to jest punkt 3. Warunek "$Z3 - gt 500" to sprawdzenie, czy różnica Z2 i Z1 jest większa od 0,5KB. Następny warunek "if `cat state` = 0" to sprawdzenie, czy aktualnie blokada jest włączona czy nie. Chodzi o to, że gdy blokada jest uruchamiana z linijki "./mlstop" zaraz potem w pliku ./mlstop jest wpisywana wartość 1. Chodzi o to, żeby program nie włączał ani nie wyłączał blokady wiele razy, skrypt mlstart i mlstop uruchomi się tylko wtedy, kiedy jest potrzeba, a nie co sekundę.
Podsumowując pliki w katalogu jakie występują: skrypt-główny, nazwany przeze mnie: "josh-pseudo-shaper" potem: "mlstart" i "mlstop" i pliki pomocnicze: "state" i "run".

Jeśli chcesz wiedzieć więcej o sterowaniu ruchem w sieciach linux przeczytaj pracę magisterską autora powyższego skryptu.

Nadesłał 15-04-2005 Witold Szczerba <pljosh@poczta,neostrada,pl>


Konfigurowanie podstawowych ustawień firewalla na przykładzie iptables

Problem: Jak ustawić firewall?

Ilość rozwiązań: 1

Rozwiązanie 1:

1. Ustawianie maskarady na naszym serwerze:

            Powinniśmy zacząć od włączenia odpowiednich opcji

            echo 1 > /proc/sys/net/ipv4/ip_forward

            Zapewnienie przekazywania naszych pakietów

            echo 0 > /proc/sys/net/ipv4/tcp_ecn

Niekiedy występuje problem z dostępem do niektórych stron www, wówczas przyczyną może być fakt, że w nowszych jądrach ECN jest standardowo włączone, dlatego go wyłączamy.

            Kolejnym krokiem jest wyczyszczenie wszystkich reguł iptables

            iptables -t nat -X
            iptables -t nat -F

            Zapewnienie reguły maskarady

            iptables -t nat  -A POSTROUTING -s xxx.xxx.xxx.xxx/mm  -o eth1 -j MASQUERADE

            gdzie:

                               xxx.xxx.xxx.xxx - oznacza adres naszej sieci lokalnej
                                mm      -  maska sieci

Powyższa linijka powoduje, że wszystkie komputery będące w naszej sieci lokalnej będą niewidoczne w Internecie - będą zamaskowane, jedynym komputerem widocznym w Internecie będzie nasz serwer. Maskarada jest świetnym rozwiązaniem gdy chcemy zapewnić dostęp do Internetu sieci lokalnej.

2. Otwieranie portów na naszym serwerze

            iptables -A INPUT -p tcp --dport AA -m state --state NEW -j ACCEPT

            Powyższa linijka powoduje otworzenie portu AA do serwisu uruchomionym na naszym serwerze.

            np. udostępnienie usługi SSH wiąże się z otworzeniem portu 22 na naszym serwerze

            iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

3. Możemy przekierować porty w sieci lokalnej.

Takie postępowanie ma na celu udostępnienie serwisów uruchomionych na komputerze lokalnym (z adresem nierutowalnym), osobom z poza naszej sieci lokalnej. Kiedy w sieci lokalnej istnieje jakiś serwer www i chcemy się pochwalić naszą stronę w Internecie wówczas możemy przekierować odpowiednie porty aby był możliwy dostęp do tego serwisu z  Internetu. Aby się dostać do danego serwisu wówczas będziemy musieli posłużyć się adresem:

            http://adres_serwera:xxx

xxx -  port na jaki przekirowany został port 80 (80 bo serwer www)

            iptables -t nat  -A PREROUTING -p tcp -d  ip_zewnetrzne --dport  XXX -j DNAT --to ip_lokalne:AA

            gdzie:

                               ip_zewnetrzne – określa nasz zewnętrzny(routowalny) numer IP
                               ip_lokalne – określa numer IP komputera w sieci lokalnej
                                XXX – określa port pod jaki mapujemy dany adres IP
                               AA  –  określa port w komputerze lokalnym

4. Możemy przekierować ruch na Serwer Proxy.

W Sieci lokalnej możemy przekierować ruch z portu 80 (jakiegoś klienta w sieci), na port, na którym mamy uruchomiony Serwer Proxy, spowoduje to, że użytkownicy chcący przeglądać strony WWW będą musieli się łączyć z Serwerm Proxy

              iptables -t nat -A PREROUTING -p tcp -s ip_lokalne --dport 80 -j REDIRECT --to-port 8080

            gdzie:

                               ip_lokalne – określa numer IP komputera w sieci lokalnej
                                8080 – to port na który pracuje u nas Serwer Proxy
                               80 – port,  który przekierowujemy

5. Polecenie ping.

Możemy ustawić odpowiednie reguły zezwalające bądź broniące pingowania naszego serwera

            - reguła nie zezwalającą na pingowanie naszego serwera

                         iptables -A INPUT -i eth1 -p icmp -j DROP

            - reguła zezwalająca na pingowanie naszego serwera

                        iptables -A INPUT -i eth1 -p icmp -j ACCEPT

                        eth1 – nasz interfejs wyjściowy na świat

Nadesłał 17-05-2004 Karol Walczak <carll0@wp,pl>


Jeśli chcesz, żeby znalazł się tutaj również Twój skrypt, bądź zmodyfikowałeś już istniejący, przyślij go wraz z opisem.

Pod skryptami znajdują się dane osoby, która wysłała post zawierający dany skrypt. Adresy e-mail są zabezpieczone przed skanerami podmianą kropek przecinkami oraz nie stosowaniem etykiet mailto: w kodzie html. Jeśli jednak nie chcesz, aby Twoje dane lub ich część widniały pod skryptem, poinformuj mnie o tym.

Wszelkie komentarze odnośnie skryptów, np. te w "Uwagach", tylko czasami są w całości cytatem z wypowiedzi osoby, która nadesłała skrypt, najczęściej komentarze te są zmodyfikowane lub napisane w całości przez autora niniejszej strony; w kilku przypadkach zacytowano też fragmenty manuali do niektórych komend uniksa.


Lista dyskusyjna skrypty
Podyskutuj z innymi o skryptach.

(nie działa z braku serwera - jeśli możesz udostępnić serwer dla listy dyskusyjnej o skryptach pod GNU Mailman - proszę o wiadomość)


Księga gości
Uwagi i opinie o niniejszej stronie.


Jeśli nie znalazłeś tutaj skryptu, którego poszukiwałeś możesz jeszcze zajrzeć do Shelldorado.


Linux Counter #322196

Idzie e-mail! Wyślij e-mail do autora niniejszej strony.

© 2003-2005 Andrzej Kasperowicz

Zabronione jest kopiowanie niniejszej strony lub jej fragmentów bez zezwolenia.

Autor niniejszej strony nie ponosi jakiejkolwiek odpowiedzialności za szkody powstałe w związku z pobieraniem bądź wykorzystywaniem materiałów znajdujących się na niniejszej stronie, nie ponosi też odpowiedzialności za rzetelność, kompletność, ani aktualność zamieszczonych na tej stronie informacji.

słowa kluczowe dla niniejszej strony: skrypty, linuksa, bash, basha, bashu, shell, powłoka, linux, scripts, skrypt, powłoki, powłoce, linuks, unix, shella, script, shellu, shellowe, shellem, perl, sed, awk, funkcje, programowanie, linuxa, linuksie, linuksem, csh, tcsh, zsh, sh, ksh, zastosowanie, przykłady, przykładowe

eXTReMe Tracker