Posts Tagged rh133

Usunięcie rozszerzenia z nazwy pliku w bashu

Prosty problem do rozwiązania: w skrypcie napisanym w Bashu z nazwy pliku usunąć jego rozszerzenie, czyli zostawić sobie tylko nazwę pliku. Przez rozszerzenie rozumiem wszystko co występuje po ostatniej kropce.

Pierwszym moim pomysłem było utworzenie wyrażenia regularnego, ale to wygląda jak strzelanie z armaty do muchy. Więc trzeba zajrzeć do dokumentacji polecenia bash, i tam można znaleźć taką oto definicję:

${parameter%word}
${parameter%%word}
        Remove matching suffix pattern.

Konstrukcja ta działa następująco: w wartości podanego parametru (parameter) wyszukuje zadany ciąg znaków (word) i w przypadku znalezienie ucina jego jak najkrótszy fragment (w przypadku użycia %) lub jak najdłuższy (w przypadku użycia %%).

Tak będzie wyglądało usunięcie jakiegoś rozszerzenia z pliku:

~$ PLIK=nazwa.jeden.dwa
~$ echo ${PLIK%.dwa}
nazwa.jeden

Jak widać w efekcie ciąg znaków .dwa został usunięty. Teraz trzeba rozszerzyć to zachowanie na dowolne rozszerzenie, czyli zamiast rozszerzenia użyć znaku * (gwiazdki):

~$ PLIK=nazwa.jeden.dwa
~$ echo ${PLIK%.*}
nazwa.jeden
~$ echo ${PLIK%%.*}
nazwa

Proszę zwrócić uwagę na różnicę pomiędzy % a %%. W przypadku użycia % zostało usunięte tylko ostatnia rozszerzenie (czyli najkrótszy ciąg mogący zostać dopasowany). Natomiast przy użyciu %% zostały usunięte znaki od wystąpienia pierwszej kropki, czyli największy zakres jaki pasował do zdefiniowanego wzorca.

Istnieje także wariant tego polecenia umożliwiający usuwanie pierwszych znaków (czyli prefiksu), zamiast znaku % należy użyć #:

${parameter#word}
${parameter##word}
        Remove matching prefix pattern.

Źródła

Tags: , , , , , , ,

Wyświetlenie zawartości pliku od końca

Ostatnio zapragnąłem obejrzeć sobie zawartość z plikiem logu serwera Apache. Cel był następujący:

  • wybrać tylko określone linie przy użyciu polecenia grep
  • wyświetlić 20 ostatnich linii
  • wyświetlić je od końca, tak aby linie które pojawiają się na końcu były wyświetlane jako pierwsze

Dwa pierwsze punkty w realizacji są proste:

grep 'GET / ' access.log | tail -n 20

Teraz pozostaje odwrócić kolejność linii. Pierwsze moje skojarzenie to polecenie sort z przełącznikiem -r, czyli coś takiego:

grep 'GET / ' access.log | tail -n 20 | sort -r

Niestety, to nie zadziała. Dostaniemy nie odwróconą zawartość pliku, ale po prostu posortowany plik od wartości największej do najmniejszej.

Więc pozostaje dodanie numeracji do pliku (polecenie cut -n i posortowanie zawartości:

grep 'GET / ' access.log | tail -n 20 | cat -n | sort -rn

Efekt tym razem odpowiedni, ale jeszcze zostały dodatkowe linie z numeracją, można je usunąć za pomocą polecenia cut:

grep 'GET / ' access.log | tail -n 20 | cat -n | sort -rn | cut -f 2-

I koniec końców efekt jest zgodny z oczekiwaniami.

Przeglądając jeszcze dokumentację do polecenia cat zauważyłem jeszcze jedną komendę: tac, która działa jako odwrotność polecenia cat. Używając tej komendy, skrypt będzie wyglądał następująco:

grep 'GET / ' access.log | tail -n 20 | tac

I po sprawie :). Morał: warto czytać strony MAN, można zaoszczędzić sporo czasu, pisania i mocy maszyny.

Źródła

Tags: , , , , ,

Kopiowanie wybranych plików z zachowaniem struktury katalogów

Stanąłem przed następującym problem: w znaleźć wszystkie pliki spełniające wybrane kryteria i skopiować je na inny udział dyskowy wraz z zachowaniem ich struktury katalogów.

Do odszukanie wszystkich wybranych plików można użyć polecenia find i można na wyszukanych plikach użyć dowolnej komendy, np cp:

find -name '*.html' -exec cp {} /mnt/kopia \;

Niestety, rozwiązanie takie nie sprawdzi się w mojej sytuacji, nie odwzoruje struktury katalogów.

Z pomocą może przyjść polecenie cpio. Polecenie to jest pewnego rodzaju odpowiednikiem komendy tar i jest używane np. przy tworzeniu archiwów RPM. Wywołanie, które pozwoli odwzorować strukturę katalogów kopiowanych plików:

find -name '*.html' -print | cpio -pdv /mnt/kopia

Poszczególne opcje komendy oznaczają:

  • -p – powoduje, że lista plików zostanie odczytana ze standardowego wejścia i następnie zostaną one skopiowane do wybranego katalogu
  • -d – w razie potrzeby tworzy strukturę katalogów
  • -v – na wyjściu błędu wypisuje informacje o kopiowanych plikach

Aktualizacja:

Można także napotkać następujący problem: nazwy plików zawierają znaki nietypowe, takie jak spacje, znaki tabulacji. Znaki te są używane przez powłokę do podziału linii poleceń na argumenty i sprawiają często problemy podczas kopiowania. W tym przypadku najprościej będzie skorzystanie z ciągów znaków zakończonych znakiem \0. Należy tylko poinformować o tym zarówno polecenie find jak i cpio:

find -name '*.html' -print0 | cpio -0 -pdv /mnt/kopia

Więcej informacji można znaleźć w dokumentacji do polecenia.

Źródła

Tags: , , ,

Przechwycenie strumienia wyjściowego wybranego procesu

Czasem istnieje następująca sytuacja: musimy zobaczyć co dana aplikacja wypisuje na ekranie, ale jest ona uruchomiona na innym terminalu (do którego nie mamy dostępu) lub też działa w tle i jej komunikaty lądują w nicości (czyli /dev/null). Można to zrobić za pomocą polecenia strace. Polecenie to służy generalnie do śledzenia wywołań systemowych.

strace -f -e trace=write -e write=1,2 -p PID

Opis opcji konfiguracyjnych:

  • -f – śledzi także procesu potomne monitorowanego procesu
  • -e trace=write – śledzenie informacji zapisu
  • -e write=1,2 – deskryptory plików, dla których mają być śledzone zapisy (tutaj stdout i stderr)
  • -p PID – numer procesu, który ma być śledzony

Demonstracja

  1. Utworzyć skrypt o nazwie trace_test.sh
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/bin/bash

    echo PID: $$

    for I in `seq 1 1000`
    do
    echo "Linia $I"
    sleep 2
    done

    Skrypt ten wyświetli numer PID z jakim został uruchomiony oraz bedzie wyświetlał komunikat co dwie sekundy.

  2. Uruchomić powyższy skrypt:
    $ bash ./trace_test.sh
  3. Należy teraz otworzyć drugą konsolę i wykonać w niej polecenie:
    strace -f -e trace=write -e write=1,2 -p PID

    W miejsce PID należy wpisać numer wyświetlony przez skrypt trace_test.sh. Przykładowy wynik działania:

    Process 14589 attached - interrupt to quit
    --- SIGCHLD (Child exited) @ 0 (0) ---
    write(1, "Linia 5\n", 8)                = 8
     | 00000  4c 69 6e 69 61 20 35 0a                           Linia 5.          |
    Process 14598 attached
    Process 14589 suspended
    Process 14589 resumed
    Process 14598 detached
    --- SIGCHLD (Child exited) @ 0 (0) ---
    write(1, "Linia 6\n", 8)                = 8
     | 00000  4c 69 6e 69 61 20 36 0a                           Linia 6.          |
    Process 14599 attached
    Process 14589 suspended
    Process 14589 resumed
    Process 14599 detached
    --- SIGCHLD (Child exited) @ 0 (0) ---
    write(1, "Linia 7\n", 8)                = 8
     | 00000  4c 69 6e 69 61 20 37 0a                           Linia 7.          |
    Process 14601 attached
    Process 14589 suspended
    Process 14589 detached
    Process 14601 detached

Analiza takich danych może nie jest najłatwiejsza, ale zawsze dobrze mieć trochę więcej informacji :).

Źródła

Tags: , , , , ,

Monitorowanie aktywności sieciowej procesu lub użytkownika

Oto prosta komenda, która pozwoli na monitorowanie, z jakimi adresami sieciowymi łączy się dana aplikacja lub też dany użytkownik:

  • monitorowanie aktywności procesu:
    lsof -r 2 -p PID -i -a
  • monitorowanie aktywności użytkownika
    lsof -r 2 -u USER -i -a

Poszczególne parametry oznaczają:

  • -p PID – numer procesu, który ma być monitorowany
  • -u USER – nazwa użytkownika, którego połączenia sieciowe mają być monitorowane, parametr może być użyte więcej niż jeden raz, może to pozwolić to wtedy na monitorowanie aktywności kilku użytkowników
  • -r 2 – tryb ciągłego odczytu, w tym przypadku co dwie sekundy zostaną wyświetlone aktualne dane
  • -i – wyświetlenie połączeń IP (pominięcie wyświetli także np. otwarte pliki), pozwala także na ograniczanie zakresu wyświetlanych opcji (np. IPv4 lub IPv6 czy jakaś pojedyncza domena)
  • -a – powoduje, że pomiędzy warunkami definiującymi co ma być wyświetlone jest stosowany spójnik logiczny AND (w przeciwnym wypadku będzie stosowany spójnik OR, czyli wyświetlenie np. informacji o podanym procesie lub wszystkie połączenie TCP)

Źródła

Tags: , , ,