Samouczek Linux

Z KdmWiki
Przejdź do nawigacji Przejdź do wyszukiwania

Praca z powłoką

Logowanie:

Aby zalogować się na zdalny komputer należy:

W systemie Windows:

Należy pobrać program PuTTY (http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html) obsługa jest intuicyjna.

Przy pierwszym logowaniu na dany komputer PuTTY wyświetli nam okienko:

Putty2.png

Komunikat ten ostrzega nas, że łączymy się z komputerem, który nie jest znany. Każdy komputer (dokładniej serwer ssh) posiada unikatowy i trudny do podrobienia identyfikator (RSA fingerprint) po którym można go rozpoznać. Zgoda spowoduje dodanie tego hosta do listy znanych komputerów, co zagwarantuje nam, że w międzyczasie nikt nie może podszyć się pod ten komputer aby podsłuchać nasze hasło.

W systemie Linux:

Do logowania z konsoli w systemie Linux służy polecenie ssh np.:

ssh sn.wcss.pl

Spowoduje ono nawiązanie szyfrowanego połączenia ze zdalnym komputerem. Szyfrowanie działa od samego początku połączenia, czyli nasze hasło również przesyłane jest w postaci zaszyfrowanej. Przy pierwszym połączeniu z danym komputerem ssh napisze cos takiego:

The authenticity of host 'sn.wcss.pl (156.17.248.129)' can't be established.
RSA key fingerprint is d5:85:f7:5a:92:9b:82:7a:d3:74:67:ab:e4:46:28:e9.
Are you sure you want to continue connecting (yes/no)?

Jest to odpowiednik informacji z PuTTYego.

Każdorazowe logowanie na zdalny komputer wymaga podania naszego hasła. Co w przypadku dłuższych haseł (trudniejszych do złamania) bywa uciążliwe. Serwer ssh pozwala na zalogowanie się za pomocą klucza RSA. Mechanizm ten pozwala określić naszą tożsamość na podstawie zapisanego na naszym dysku klucza prywatnego. Dopóki nikt nie zdobędzie naszego klucza prywatnego możemy czuć się bezpiecznie.

Logowanie za pomocą klucza ma jedną wadę. Jeżeli ktoś włamie się na nasz komputer to będzie mógł się zalogować na wszystkie komputery, które wpuszczają nas bez hasła.

Aby korzystać z logowania za pomocą klucza prywatnego musimy go najpierw wygenerować. Służy do tego polecenie:

ssh-keygen -t RSA

Wygeneruje ono parę kluczy - prywatny i publiczny i zapisze jako .ssh/id_rsa i .ssh/id_rsa.pub. Klucz publiczny (id_rsa.pub) należy umieścić na komputerach na które się chcemy zalogować. Ten klucz może być znany przez osoby trzecie. Zawartość pliku id_rsa powinna być chroniona przed niepowołanym dostępem (domyślnie ma prawa do odczytu tylko przez nas) ponieważ to ona jest naszą przepustką pozwalającą się zalogować na zdalnym komputerze.

Kolejną rzeczą, którą należy zrobić jest skopiowanie klucza publicznego na wybrany komputer:

ssh-copy-id -i ~/.ssh/id_rsa.pub uzytkownik@sn.wcss.pl

Jeżeli wszystko się udało i zdalny komputer pozwala na uwierzytelnianie za pomocą klucza (większość pozwala), to po wydaniu polecenia:

ssh sn.wcss.pl

powinniśmy zostać zalogowani bez pytania o hasło.

Aby się wylogować należy wpisać exit lub logout.

Przydatne polecenia:

  • CTRL+l clear czyści ekran
  • CTRL+d exit wylogowanie
  • SHIFT+PgUp pokazuje starszą zawartość ekranu
  • strzałka w górę pokazuje poprzednie polecenia
  • TAB dopełnia polecenia i nazwy plików (TAB TAB pokazuje wszystko)

Uruchamianie programów

Aby uruchomić program np. Midnight Commander, należy wpisać w konsoli jego nazwę w tym wypadku mc. Katalogi, które system przeszukuje znajdują się w zmiennej $PATH. Można wypisać jej zawartość w ten sposób:

echo $PATH

Jak widać, nie ma tam naszego katalogu, zatem jeżeli skompilujemy sami jakiś program, napiszemy skrypt, lub zainstalujemy coś w swoim katalogu domowym nie będzie można uruchomić tego w standardowy sposób. Są dwie możliwości uruchomienia takiego programu: podać pełną ścieżkę do pliku wykonywalnego, lub dodać jego katalog do zmiennej PATH.

  • Utworzyliśmy skrypt o nazwie test w katalogu domowym i chcemy go uruchomić podając pełną ścieżkę:
user@bem:~$ ./test
  • Uruchamiamy za pomocą zmiennej PATH:
user@bem:~$ export PATH=$PATH:/home/user/
user@bem:~$ test

Jeżeli chcemy aby nasza zmienna została zapamiętana należy pierwszy z tych wierszy umieścić w pliku .bashrc.

Uruchomione programy zajmują nam konsolę, co oznacza, że nie możemy w czasie działania programu uruchomić drugiego, ani nawet sprawdzić zawartości katalogu. Aby sobie z tym poradzić można program uruchomić w "tle" dodając znaczek ampersand (&) po jego nazwie. Aby przywrócić program do normalnego trybu należy użyć polecenia fg (foreground). Już działający program można również zmusić do zwolnienia konsoli. Aby tego dokonać należy nacisnąć CTRL+z co spowoduje zatrzymanie programu, a potem wpisać jedno z poleceń fg (aby przywrócić go), bg (aby kontynuować wykonanie w tle). Polecenie jobs pokaże nam jakie i ile programów chodzi w tle.

Strumienie

Z każdym wykonującym się programem (procesem) skojarzone są trzy strumienie: wejściowy (stdin), wyjściowy (stdout) i strumień wyjściowy dla błędów (stderr). Strumień wejściowy jest to zwykle ciąg znaków wpisanych z klawiatury, strumienie wyjściowe są wypisywane na ekranie. Wszystkie strumienie można w bashu przekierować, czyli zmienić ich domyślne zachowanie. Jeżeli nasz program wymaga za każdym razem wprowadzenia z klawiatury jakichś parametrów, a chcemy uruchamiać go więcej razy, dużo wygodniej będzie jeżeli zapiszemy je w jakimś pliku np. input.txt i uruchomimy nasz program tak:

user@bem:~$ input.txt > program

Analogicznie zachowują się strumienie wyjściowe, ale z racji, że są dwa zostały ponumerowane: 1 - stdout, 2 - stderr (domyślnie przyjmowane jest, że przekierowyjemy stdout). Zatem aby zapisać wynik programu do pliku out, a ewentualne błędy do err należy napisać:

user@bem:~$ program 1>out 2>err

Jeżeli chcemy mieć oba strumienie w jednym pliku (tak jak to jest na ekranie), to trzeba je połączyć:

user@bem:~$ program 2>&1 >err

Obok zapisywania do plików jest też możliwość przekierowania wyjścia jednego programu na wejście drugiego, służy d o tego operator | (pipe).

user@bem:~$ echo ".atok am alA" | tr '.' '!' | rev | cowsay

Powyższy zapis oznacza: wyjście pierwszej komendy czyli ".atok am alA" przekaż na wejście programu tr, który zamieni kropki na wykrzykniki, wyjście z tr przekaż na wejście programu rev, który odwraca otrzymany napis. A wyjście rev przekaż do programu cowsay, który zajmuje się zaawansowaną obróbką tekstu. W wyniku otrzymamy:

 ______________
< Ala ma kota! >
 --------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||


Sygnały

Każdemu wykonywanemu procesowi można wysłać sygnał. Niektóre sygnały wysyła jądro systemu, niektóre są do dyspozycji użytkownika. Sygnały służą do sterowania wykonaniem programu. Np. jeżeli nasz proces będzie próbował odczytać coś z pamięci innego procesu to otrzyma od systemu sygnał SIGSEGV, co spowoduje jego natychmiastowe zakończenie z komunikatem "Segmentation fault". Sygnałami przydatnymi z punktu widzenia użytkownika są np.

  • SIGINT
  • SIGKILL
  • SIGSTOP
  • SIGCONT

Do wysyłania sygnałów do dowolnego procesu służy program o niewinnie brzmiącej nazwie "kill". Wywołujemy go w ten sposób:

kill -sKILL <PID>

gdzie <PID> zastępujemy numerem procesu który chcemy unieszkodliwić. Nie można użyć nazwy programu, gdyż program może być uruchomiony w kilku kopiach i system nie będzie wiedział o które nam chodzi. Jeżeli chodzi o wszystkie to możemy użyć programy killall:

killall -sKILL bash

Powyższe polecenie zakończy wszystkie sesje basha (należące do nas) i popsuje nam zabawę. Sygnał SIGINT można wysłać do aktywnego programu za pomocą skrótu CTRL-C, jest to chyba najwygodniejsze przerwanie właśnie uruchomionego programu. Jeżeli na naszym komputerze trwają jakieś obliczenia a chcemy zrobić coś innego i komputer działa zbyt wolno można użyć sygnału STOP. Polecenie:

kill -sSTOP <PID>

spowoduje zatrzymanie (nie przerwanie) działania programu i zwolni nam procesor. Aby wznowić ten program wysyłamy mu kolejny sygnał - CONT:

kill -sCONT <PID>

i wszystko wraca do normy.


Pliki i katalogi

Podstawowe informacje

Po zalogowaniu jesteśmy automatycznie umieszczani w naszym katalogu domowym, zwykle /home/user/. Do zmiany bieżącego katalogu służy polecenie cd.

  • cd katalog
  • cd /usr/local/bin
  • cd ../

Dwie kropki oznaczają wyjście do katalogu o poziom wyższego. Aby wyświetlić pliki znajdujące się w bieżącym katalogu należy wywołać polecenie ls. Parametrami ls są np. l (wyświetl w formie listy), a (wyświetl pliki ukryte), h (podaj rozmiar w czytelniejszej postaci).

user@bem:~/$ ls -lah
drwxrwxr-x 4 user users 128K 2008-02-29 14:39 ala -rwxr-xr-x 1 user users 8,4K 2008-02-18 12:41 a.out -rw-r--r-- 1 user users 2 2008-01-30 13:13 B

Po lewej stronie znajdują się prawa dostępu do pliku/katalogu. User jest nazwą właściciela pliku, users nazwą jego grupy, za nimi znajduje się rozmiar pliku, data utworzenia i nazwa. Prawa dostępu są czytane w następujący sposób:

Prawa dostepu.png

Typ d oznacza, że mamy do czynienia z katalogiem, r oznacza prawo do odczytu (read), w do zapisu (Write) i x do wykonania (eXecute). Aby zmienić prawa pliku lub katalogu na przykład na takie które nie pozwolą go odczytać nikomu poza nami (i administratorem) można użyć polecenia chmod.

chmod og-r B

Co jak się można domyślić oznacza zabranie (znak minus) praw do odczytu (literka r) dla grupy i dla innych (literki g i o). Tak samo można dodawać prawa, jeżeli plik B jest skryptem to możemy mu nadać prawo do wykonywania.

chmod +x B

Pominięcie o,g i u spowoduje ustawienie praw do wykonania dla wszystkich, czyli:

ls -lah B
-rwx--x--x 1 user users 2 2008-01-30 13:13 B

Przydatne programy:

  • du -h <nazwa_katalogu> - podaje rozmiar pliku lub katalogu z wszystkimi podkatalogami
  • df -h - podaje ilość wolnego miejsca na dyskach
  • file <nazwa_pliku> - podaje sporo informacji o pliku, np. rozmiar obrazka w pikselach

Kopiowanie

Do kopiowania plików służy polecenie cp. Składnia wygląda następująco:

cp -r <źródło> <cel>

Flaga r (recursive) służy do kopiowania katalogów i mówi, że mają być skopiowane wszystkie podkatalogi. Przykładowe uzycie:

  • cp plik /tmp - kopiuje plik do katalogu /tmp
  • cp katalog1/* katalog2/ - kopiuje wszystkie pliki z katalog1 do katalog2 (omijając podkatalogi)
  • cp -r katalog1 /tmp/katalog3 - kopiuje cały katalog1 wraz z podkatalogami do katalogu /tmp jako katalog3
  • mv katalog1 katalog2 - zmienia nazwę katalog1 na katalog2

Aby skopiować pliki między komputerami na przykład z naszego komputera domowego na komputer bem należy użyć polecenia scp. Scp kopiuje pliki połączeniem szyfrowanym. Osiąga maksymalnie ok. 10MB/s, o ile nasze łącze na to pozwala.

  • scp plik user@bem.wcss.pl:~/ - kopiuje plik na komputer bem do naszego katalogu domowego
  • scp -Cr katalog user@bem.wcss.pl:~/ - kopiuje katalog, flaga C włącza kompresję (warto użyć przy słabszym połączeniu)
  • scp user@bem.wcss.pl:~/plik ./ - kopiowanie w drugą stronę, czyli ze zdalnego komputera na lokalny

W systemie Windows jest również program do kopiowania plików na komputery linuksowe - WinSCP (http://winscp.net/).

Kompresja

Najpopularniejszym formatem skompresowanych plików w systemach unixowych jest gz i nowszy bz2. Jeżeli chcemy wymieniać pliki z użytkownikami Windows lepiej będzie je spakować do formatu zip.

Kompresja:

  • zip -r arch.zip katalog
  • tar -cvzf arch.tar.gz katalog
  • tar -cvjf arch.tar.bz2 katalog

Dekompresja:

  • unzip arch.zip
  • tar -xvzf arch.tar.gz
  • tar -xvjf arch.tar.bz2

Przydatne programy

Wyszukiwanie w tekście - grep

Program grep pozwala znaleźć wszystkie wystąpienia wzorca w zadanym tekście. Tekst wejściowy może znajdować się w pliku, lub być podanym na standardowe wejście, a co za tym idzie może być przekierowany z wyjścia dowolnego innego polecenia.

grep Ala plik.txt

Wypisze wszystkie wiersze z pliku plik.txt zawierające przynajmniej jedno wystąpienie słowa Ala. Następujące polecenie wykonuje analogiczne przeszukiwanie ale na wyjściu innego polecenia:

find ./ | grep Ala

Jak można się domyślić wypisane zostaną wszystkie pliki zawierające w nazwie, albo ścieżce słowo Ala.

Grep jest case sensitive co oznacza, że wielkość liter ma znaczenie i Ala, aLa i alA są trzema różnymi wzorcami. Aby wyłączyć rozróżnianie wielkości liter należy użyć przełącznika -i. Warto też zapamiętać przełączniki: --color, -v, -R. Pierwszy z nich powoduje, że grep koloruje każde dopasowanie wzorca, drugi neguje zapytanie a trzeci włącza tryb rekursywny.

Wyszukiwanie pojedynczego wzorca nie wyczerpuje możliwości tego programu. Pozwala on na wyszukiwanie całej klasy napisów, które można definiować za pomocą wyrażeń regularnych. Mają one w uproszczeniu taką składnię:

  • napis np. Abc, 42 j21
  • . np. A.c
  • [] np. [abc]
  • $ i ^ np. ^napis, napis$, ^napis$
  • * np. g*
  • {} np. .{1,2}

Nasz przykładowy tekst który będzie przeszukiwany to:

1. Kiedy się tu spotkamy jeszcze?
gdy błyśnie piorun, luną deszcze?
2. Gdy wrzawa ciszy ulegnie
Ktoś zwycięży, ktoś polegnie.
3. Zanim słońce z niebios zbiegnie.
1. Gdzie?
2. Na skraju wrzosowiska.
3. By Macbetha ujrzeć z bliska.


Dopasowywanie napisu było pokazane wcześniej. Kropka "." dopasowuje się do dowolnego znaku, a nawiasy kwadratowe dopasowują się do pojedynczego znaku, ale tylko takiego który zawierają np.

user@bem:~/$ grep --color .eszcze ../makbet
1. Kiedy się tu spotkamy jeszcze?
gdy błyśnie piorun, luną deszcze?

To samo z wykorzystaniem nawiasów:

user@bem:~/$ grep --color [jd]eszcze ../makbet
1. Kiedy się tu spotkamy jeszcze?
gdy błyśnie piorun, luną deszcze?

Druga wersja różni się tym, że juz nie dopasuje słowa "leszcze". Kolejne znaczki: ^ i $ służą do kotwiczenia wyrażenia odpowiednio na początku i na końcu wiersza.

user@bem:~/$ grep --color ^[jd]eszcze ../makbet

Nie znajdzie żadnego trafienia. Ale można nim znaleźć tekst "deszcze niespokojne" o ile zaczyna się od początku wiersza.

Jeżeli chcemy podać wyrażenie opisujące cały wiersz należy użyć dwóch kotwic jednocześnie. Jeżeli chcemy wypisać z pliku wszystkie wiersze zawierające sekwencję nukleotydową postaci: actgctag... To możemy to zrobić w następujący sposób:

user@bem:~/$ grep --color grep ^[acgt]*$ ../seq

Szukanie plików - find i locate

Narzędzie find służy do wyszukiwania plików o zadanych parametrach. Pozwala na ustalenie takich kryteriów jak czas modyfikacji/utworzenia pliku, jego nazwa, prawa dostępu czy nazwa właściciela.

Kompletny spis opcji można znaleźć w podręczniku polecenia find.

man find

Przykładowe użycie:

  • find -name ”frac1.png” : plik o wskazanej nazwie
  • find ./ -ctime 0 : pliki utworzone dzisiaj
  • find ./ ’*.txt’ : pliki o rozszerzeniu txt

Drugim narzędziem, które służy do podobnych celów jest locate. Podstawowa różnica jest taka, że locate nie przeszukuje dysku tylko bazę danych. Dzięki temu wyszukiwanie przez locate jest wielokrotnie szybsze od find, ale wyszukuje jedynie te pliki, które istniały w czasie tworzenia bazy. Na komputerach WCSS baza ta tworzona jest raz dziennie.

Skrypty

Podstawy

Powyższe przykłady pokazują jak wiele różnych rzeczy można zrobić w Linuksie z poziomu wiersza poleceń. Do tej pory nierozwiązana pozostała kwestia wygody użytkowania. W tym miejscu z pomocą przychodzą skrypty. Z technicznego punktu widzenia skrypt w systemie Linux to jest plik, który zawiera nazwę programu do uruchomienia i dane które do tego programu należy wysłać (standardowym wejściem). Najczęściej nazwą programu (interpretera) jest powłoka sh/bash/csh/ksh, lub jakiś język skryptowy perl/python/ruby. Aby uruchomić skrypt należy nadać mu najpierw prawa do wykonania, robi się to w następujący sposób:

chmod +x nasz_skrypt

potem aby uruchomić należy napisać:

./nasz_skrypt

Przykładowy skrypt, który ma zostać wykonany przez powłokę systemu wygląda tak:

#!/bin/bash

echo "Witaj Świecie";

Wiersz: "#!/bin/bash" określa interpreter do wykonania skryptu, poniżej znajdują się polecenia do wykonania.

W skryptach można umieszczać zupełnie dowolne polecenia systemowe, własne programy lub nawet inne skrypty. Należy pamiętać, że przy wykonywaniu skryptu uruchamiany jest nowa kopia basha, która wykonuje nasz skrypt. Zatem coś takiego:

#!/bin/bash

ZMIENNA = 3;

nie spowoduje ustawienia tej zmiennej w naszym systemie.

Pętle

Jeżeli chcemy jakieś polecenie wykonać więcej niż raz możemy użyć do tego celu pętli. Skrypt postaci:

#!/bin/bash

for((i=0; i<5; i++));
do
echo "Przebieg numer $i";
done;

wypisze:

Przebieg numer 0
Przebieg numer 1
Przebieg numer 2
Przebieg numer 3
Przebieg numer 4

Oprócz wykonywania pętli dla kolejnych liczb przydatne jest wykonywanie pętli dla plików w katalogu. Dobrym przykładem jest wykonanie miniaturek wszystkich plików JPEG znajdujących się w bieżącym katalogu.

#!/bin/bash

for i in *.jpg;
do
convert -resize 640 $i mini_$i;
done;

Powyższy skrypt dla każdego pliku z rozszerzeniem jpg uruchomi program convert (z pakietu ImageMagick) aby wykonał miniaturę tego obrazka (zdjęcia) o szerokości 640px.

Wyrażenia warunkowe

Obok pętli kolejnym sposobem na sterowanie wykonaniem skryptu są wyrażenia warunkowe. Wyrażenie takie pozwala na uzależnienie wykonania jakiegoś polecenia od zajścia logicznego warunku. Przykład może być następujący:

#!/bin/bash

grep Ala ~/dziennik.txt 2>&1 1>/dev/null;

if [ $? = "0" ]; then
   echo "Znaleziono";
   else
   echo "Nie znaleziono";
   fi;

Powyższy skrypt sprawdza czy w pliku dziennik.txt znajduje się słowo Ala. Najpierw za pomocą polecenia grep szuka w pliku dziennik.txt imienia Ala. Jak było wcześniej grep w przypadku znalezienia słowa wypisuje cały wiersz z pliku. Aby tego nie robić przekierowujemy wyjście do /dev/null - nic już nie zostanie wypisane. Większość poleceń w Linuksie zwraca do systemu liczbę, która niesie z sobą jakieś informacje. Liczba ta umieszczana jest w zmiennej $?. Grep zwraca 0 jeżeli znajdzie coś, lub 1 w przypadku braku trafień. Poniżej w warunku if sprawdzamy zmienną $? zawierającą rezultat pracy programu grep, jeżeli jest równa 0 to wykonane zostanie pierwsze polecenie, w przeciwnym wypadku wykonane zostanie to co jest po else.

Więcej informacji można znaleźć tutaj: Bash programming introduction.

Pytania proszę kierować na adres: Wojciech Waga

Przykładowe zastosowania

Backup

Jeżeli obawiamy się o cenne dane i chcemy mieć ich kopię możemy napisać prosty skrypt, który co zadany okres będzie kompresował nasz cenny katalog i np. wysyłał nam pocztą:

#/bin/bash
data=`date +'%Y-%m-%d_%H-%M'`;
tar -cvjf  $data.tar.bz2   /home/user/cenny_katalog/ 1>/dev/null 2>/dev/null
echo " " | mutt -s "backup $data" -a $data.tar.bz2 wojciech.waga@pwr.wroc.pl

Skrypt ten będzie tworzył pliki o nazwie postaci:

2008-04-01_00-00.tar.bz2

i wysyłał pocztą na wskazany adres. Aby jakiekolwiek polecenie wykonywało się regularnie możemy użyć programu cron. W naszym przypadku będzie to tak:

crontab -e

Teraz w edytorze wpisujemy:

0 0 * * * /home/user/nasz_skrypt

co spowoduje uruchamianie naszego skryptu codziennie o godzinie 0:00, można oczywiście wybrać inną godzinę i większą lub mniejszą częstość backupów.