Co to jest strace?

W świecie Linuksa, większość operacji, jakie wykonuje program – od otwarcia pliku, przez połączenie z siecią, aż po odczytanie czasu – odbywa się za pośrednictwem wywołań systemowych (system calls). Są to specjalne funkcje jądra, które programy “proszą” o wykonanie niskopoziomowych zadań.

strace (skrót od “system call trace”) to potężne narzędzie diagnostyczne, które pozwala na “podsłuchanie” i wyświetlenie wszystkich tych wywołań systemowych, jakie wykonuje dany proces w czasie rzeczywistym. Dzięki temu możemy dokładnie zobaczyć, co program robi “pod maską”.

Dlaczego strace jest tak użyteczny?

strace jest niezastąpiony w sytuacjach, gdy program nie działa tak, jak powinien, a jego własne logi nic nam nie mówią. Pozwala odpowiedzieć na pytania takie jak:

  • Dlaczego ten program nie może otworzyć pliku? (Może szuka go w złej ścieżce? Może nie ma uprawnień?)
  • Dlaczego ten program tak wolno działa? (Może ciągle próbuje połączyć się z niedostępnym adresem sieciowym?)
  • Do jakich plików konfiguracyjnych odwołuje się ten proces?

Jak używać strace? Podstawowe zastosowania

1. Uruchamianie programu pod strace

Najprostszym sposobem użycia strace jest uruchomienie z nim dowolnego programu. strace wyświetli każde wywołanie systemowe wykonane przez ten program.

# Zobaczmy, co robi proste polecenie 'ls'
strace ls

Wynik będzie bardzo szczegółowy, ale już na pierwszy rzut oka zobaczymy wywołania takie jak openat() (otwieranie plików), read() (czytanie), write() (pisanie na standardowe wyjście) i close() (zamykanie plików).

2. Podpinanie się do działającego procesu

To najczęstszy i najbardziej użyteczny scenariusz. Jeśli masz już uruchomiony proces (np. serwer WWW, bazę danych), który sprawia problemy, możesz podpiąć się do niego za pomocą strace, podając jego identyfikator procesu (PID).

# Najpierw znajdź PID procesu (np. serwera nginx)
pidof nginx

# Załóżmy, że PID to 1234. Podpinamy się:
sudo strace -p 1234

Od tego momentu, każde wywołanie systemowe wykonane przez proces o PID 1234 zostanie wyświetlone w Twoim terminalu. Aby zakończyć, wciśnij Ctrl+C.

Praktyczne przykłady i przydatne opcje

Przykład: Program nie może znaleźć pliku

Wyobraź sobie, że program moj-program przy starcie zgłasza błąd “nie można otworzyć pliku konfiguracyjnego”, ale nie mówi, gdzie go szuka. Użyjmy strace, aby się tego dowiedzieć. Będziemy filtrować tylko wywołania związane z otwieraniem plików (openat).

strace -e trace=openat moj-program

Na wyjściu zobaczysz coś w stylu:

openat(AT_FDCWD, "/etc/moj-program.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/home/user/.config/moj-program.conf", O_RDONLY) = -1 ENOENT (No such file or directory)

Teraz dokładnie wiesz, w jakich lokalizacjach program szukał swojego pliku konfiguracyjnego i dlaczego go nie znalazł.

Inne przydatne opcje strace

  • -o <plik>: Zapisuje wynik do pliku zamiast na ekran.
    sudo strace -p 1234 -o /tmp/strace.log
    
  • -f: Śledzi również wszystkie procesy potomne (forks/clones). Bardzo ważne przy analizie złożonych aplikacji, jak serwery WWW.
  • -t: Pokazuje czas wykonania każdego wywołania.
  • -s <rozmiar>: Określa maksymalną długość wyświetlanych ciągów znaków (domyślnie skracane).
  • -e trace=<zestaw>: Filtruje wywołania do konkretnego zestawu. Przykłady:
    • trace=file: Tylko wywołania związane z plikami (open, read, write, close).
    • trace=network: Tylko wywołania sieciowe.
    • trace=process: Tylko wywołania związane z zarządzaniem procesami.

Podsumowanie

strace to potężne narzędzie, które daje Ci rentgenowski wgląd w działanie dowolnego programu. Choć na początku jego output może wydawać się przytłaczający, nauka filtrowania i interpretowania najważniejszych wywołań systemowych jest jedną z najbardziej opłacalnych inwestycji w Twoje umiejętności debugowania w systemie Linux. To narzędzie, które wielokrotnie uratuje Cię w trudnych sytuacjach.