SSD Nodes Learn 🎉 VPS od $5.50/mies.
Przewodniki Matt ConnorAutor: Matt Connor

df pokazuje pełny dysk a du nie: jak znaleźć miejsce

Dysk VPS jest pełny, mimo że du nie widzi zajętego miejsca? Dowiedz się, jak zlokalizować usunięte pliki trzymane przez procesy za pomocą lsof i zwolnić przestrzeń bez restartu.

Dlaczego df wskazuje pełny dysk, a du pokazuje co innego

df zgłasza, że dysk jest pełny, podczas gdy du nie znajduje zajętego miejsca, ponieważ proces nadal utrzymuje otwarty plik, który został usunięty. Usunięcie pliku usuwa jedynie jego nazwę z katalogu. Bloki danych są zwalniane dopiero w momencie zamknięcia ostatniego deskryptora pliku wskazującego na dany inode. du przeszukuje nazwy, więc nie zlicza usuniętych plików. df pyta system plików o liczbę przydzielonych bloków, dlatego nadal uwzględnia plik, który nie posiada już nazwy.

Niniejszy przewodnik odtwarza tę sytuację na standardowym VPS z systemem Ubuntu przy użyciu zainstalowanych narzędzi, lokalizuje proces blokujący plik za pomocą /proc i zwalnia miejsce bez konieczności restartu. Pozostałe przyczyny tego samego objawu to: wyczerpanie tablicy inode, pliki ukryte pod punktem montowania oraz bloki zarezerwowane dla użytkownika root.

Należy wykonać każde polecenie i przeanalizować jego wynik. Wartości zależą od konfiguracji dysku, dlatego należy porównać stan przed i po operacji na własnej maszynie, zamiast odnosić się do wartości podanych w przewodniku.

Co zlicza df, a co zlicza du

df (disk free) odpytuje każdy zamontowany system plików o jego własne statystyki: ile bloków istnieje, ile jest przydzielonych, a ile wolnych. Narzędzie to nigdy nie otwiera katalogów. Wynik obejmuje każdy przydzielony blok, w tym bloki należące do plików, do których nie prowadzi żaden wpis w katalogu.

du (disk usage) działa odwrotnie. Rozpoczyna pracę od podanej ścieżki, odczytuje katalogi, wykonuje operację stat na każdym znalezionym wpisie i sumuje bloki. Plik bez nazwy jest dla niego niewidoczny. Podobnie każdy katalog, do którego odczytu użytkownik nie ma uprawnień, dlatego zwykły użytkownik uzyskuje mniejszy wynik niż root. Przed wyciągnięciem wniosków z porównania należy uruchomić du z uprawnieniami sudo.

Przy każdym porównaniu tych dwóch narzędzi istotne są dwie opcje.

  • -x ogranicza du do jednego systemu plików. Bez tej opcji du / wchodzi do każdego systemu plików zamontowanego poniżej / i generuje sumę, której df / nigdy nie mierzył.
  • -s wypisuje jedną linię podsumowania dla każdego argumentu zamiast jednej linii dla każdego katalogu.

Pozwala to na uruchomienie pary poleceń obok siebie dla wybranego systemu plików.

df -h /
sudo du -xhs / 2>/dev/null

df odpowiada natychmiast. du zajmuje minuty w przypadku dużego systemu plików, ponieważ dla każdego pliku po drodze wykonuje operację stat. Gdy wyniki znacznie się różnią, a du zostało uruchomione jako root z flagą -x, brakujące miejsce jest przydzielone do obiektu, który nie posiada nazwy.

Celowe wywołanie niespójności

Wykonaj te czynności na testowym VPS. Wszystkie poniższe polecenia korzystają z bash oraz coreutils, więc nie wymagają instalacji dodatkowego oprogramowania.

Zarejestruj stan początkowy systemu plików, na którym znajduje się /var/tmp.

cd /var/tmp
df -h .
df --output=used -B1 .

Drugie polecenie wyświetla liczbę użytych bajtów bez zaokrągleń, co pozwala na precyzyjną weryfikację na końcu.

Teraz utwórz plik. Jego rozmiar wynika z ilości wolnego miejsca raportowanego przez system, dzięki czemu demonstracja zadziała na dowolnym dysku.

free=$(df --output=avail -B1 . | tail -n 1)
fallocate -l $((free / 10)) ghost.bin
ls -l ghost.bin
df -h .

$(...) to podstawienie polecenia: powłoka wykonuje polecenie wewnątrz, a jego wynik staje się wartością free. Jeśli ta składnia jest nowa, podstawienie polecenia w bash zawiera szczegółowe wyjaśnienie. fallocate rezerwuje rzeczywiste bloki bez ich zapisywania, dlatego kończy działanie natychmiast. Na systemie plików, który tego nie obsługuje, polecenie zakończy się błędem, a head -c $((free / 10)) /dev/zero > ghost.bin wykona to samo zadanie, zapisując bajty na dysku.

Porównaj ten df -h . z zarejestrowanym wcześniej. Kolumna użytego miejsca wzrosła, a kolumna dostępnego miejsca zmalała.

Teraz przytrzymaj plik otwarty przez inny proces, a następnie usuń go.

sleep infinity < ghost.bin &
holder=$!
rm ghost.bin
ls -l ghost.bin
df -h .
sudo du -xhs . 2>/dev/null

Przekierowanie jest kluczem do tego mechanizmu. sleep infinity < ghost.bin & uruchamia proces w tle, którego standardowym wejściem jest ten plik, więc powłoka otwiera plik i przekazuje deskryptor do sleep, który utrzymuje go w stanie otwartym. $! przechowuje identyfikator procesu (PID) tego zadania w tle. rm następnie usuwa nazwę pliku, podczas gdy deskryptor pozostaje otwarty.

Odczytaj wynik. ls nie może odnaleźć pliku, ponieważ nazwa została usunięta. du wskazuje wartość zbliżoną do początkowej, ponieważ operuje na nazwach plików. df nie zmieniło się, ponieważ bloki są nadal zaalokowane. System plików i drzewo katalogów są teraz niespójne, a różnica między nimi to właśnie usunięty przed chwilą plik.

Znajdowanie procesu blokującego usunięty plik

Każdy otwarty deskryptor pliku pojawia się w /proc/<pid>/fd/ jako dowiązanie symboliczne do pliku, do którego się odnosi. Gdy plik zostanie odlinkowany, jądro oznacza cel tego dowiązania jako usunięty. Zatem znalezienie posiadacza oznacza znalezienie dowiązania, którego cel posiada ten znacznik.

sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null

-lname dopasowuje cel dowiązania symbolicznego zamiast jego nazwy, %p wypisuje ścieżkę deskryptora, a %l wypisuje to, na co on wskazuje. Identyfikator procesu (PID) jest drugim elementem ścieżki, którą wypisuje. Uruchom to z sudo, ponieważ w przeciwnym razie można odczytać /proc/<pid>/fd tylko dla własnych procesów. Przekierowanie stderr usuwa komunikaty o procesach, które zakończyły działanie w trakcie skanowania przez find.

Obciążony serwer w każdej chwili przetrzymuje kilka usuniętych plików, a większość z nich jest mała i nieszkodliwa. Posortuj je według rozmiaru, aby tylko te istotne pozostały na górze.

sudo bash -c 'for fd in /proc/[0-9]*/fd/*; do
  target=$(readlink "$fd" 2>/dev/null) || continue
  case "$target" in
    *"(deleted)") echo "$(stat -Lc %s "$fd" 2>/dev/null) $fd $target" ;;
  esac
done' | sort -rn | head

stat -L podąża za dowiązaniem do samego inoda, więc %s raportuje rozmiar pliku, który nie posiada już nazwy. Sortowanie według tej liczby umieszcza największy plik na początku.

Następnie zidentyfikuj proces stojący za wybranym deskryptorem. Ścieżka na górze tej listy zawiera oba potrzebne numery, więc umieść je najpierw w zmiennych, zastępując PID i N wartościami wypisanymi przez własne zestawienie.

pid=PID
n=N
ps -o pid,user,etime,args -p "$pid"
sudo stat -L "/proc/$pid/fd/$n"

ps podaje nazwę programu i pokazuje, jak długo jest uruchomiony. stat -L wypisuje rozmiar i liczbę przydzielonych bloków usuniętego inoda. Razem odpowiadają na kluczowe pytanie: która usługa utrzymuje ten plik przy życiu.

Jeśli maszyna posiada już lsof, sudo lsof +L1 wyświetla otwarte pliki, których licznik dowiązań spadł do zera, i pokazuje rozmiary w jednej tabeli. Narzędzie to nie jest obecne w minimalnym obrazie Ubuntu, a instalacja pakietu w systemie plików bez wolnego miejsca może sama w sobie zakończyć się niepowodzeniem, dlatego metoda z użyciem /proc jest wersją, która działa zawsze.

Zwalnianie miejsca bez restartu

Restart rozwiązuje problem, ale jest niewłaściwym pierwszym krokiem: powoduje przestój usługi i niszczy dowody. Istnieją cztery łagodniejsze opcje, które należy wypróbować w podanej kolejności.

Najpierw skopiuj dane, jeśli nadal są potrzebne. Odczytanie ścieżki deskryptora pozwala odczytać aktywny i-węzeł (inode).

sudo cp /proc/<pid>/fd/<n> /root/recovered.log

Jest to jedyny przypadek, w którym usunięty plik można łatwo odzyskać, dlatego odzyskiwanie plików usuniętych za pomocą rm -rf zaczyna się od sprawdzenia, czy proces nadal utrzymuje otwarty plik. Gdy ostatni deskryptor zostanie zamknięty, ta ścieżka znika.

Po drugie, opróżnij plik za pomocą deskryptora. Ścieżka /proc prowadzi do tego samego i-węzła, więc jego wyzerowanie (truncate) zwalnia bloki, podczas gdy proces nadal działa.

sudo truncate -s 0 "/proc/$pid/fd/$n"
df -h /

Działa to poprawnie, gdy proces zapisujący otworzył plik w trybie dopisywania (append), ponieważ każdy zapis trafia wtedy na bieżący koniec pliku. Jeśli tak nie jest, proces zachowuje stary offset zapisu, więc kolejny zapis trafi daleko w głąb pliku i odtworzy go z luką na początku. Luka nie jest alokowana, więc bloki pozostają wolne, a df zachowuje odzyskane miejsce. To, co powraca, to jedynie rozmiar: uruchom ponownie sudo stat -L "/proc/$pid/fd/$n" po zapisie przez proces, a wyświetli on stary rozmiar obok liczby bloków, która już się z nim nie zgadza. Zrestartuj proces, jeśli chcesz, aby rozmiar również zaczął się od zera.

Po trzecie, poproś usługę o ponowne otwarcie logów. Demon, którego plik dziennika został usunięty w trakcie działania, jest typowym przykładem tego problemu. Wiele demonów otwiera ponownie pliki logów po otrzymaniu sygnału: nginx używa SIGUSR1, a rsyslog używa SIGHUP. Sprawdź dokumentację danego demona zamiast zgadywać, ponieważ wysłanie niewłaściwego sygnału do niewłaściwego demona spowoduje jego zatrzymanie.

sudo systemctl kill -s USR1 nginx

Po czwarte, zrestartuj jednostkę. sudo systemctl restart <unit> zamyka każdy deskryptor utrzymywany przez stary proces, więc bloki wracają z pewnością. W powyższej demonstracji posiadaczem jest sleep, który uruchomiłeś samodzielnie, więc jego zakończenie jest wystarczające.

kill $holder
df -h .
df --output=used -B1 .
sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null

Porównaj liczbę użytych bajtów z wartością zanotowaną przed utworzeniem pliku. Znowu się zgadzają, a find nie raportuje już twojego deskryptora. Weryfikacja za pomocą tego samego polecenia, które wykryło problem, jest nawykiem wartym utrzymania.

Obserwowanie zmiany tej wartości jest łatwiejsze niż ręczne uruchamianie df w kółko. watch powtarza polecenie w stałym odstępie czasu i odświeża wynik w tym samym miejscu, więc watch df -h / pokazuje zmianę w kolumnie użycia w miarę odzyskiwania miejsca.

Gdy sumy się zgadzają, a dysk nadal jest pełny

Jeśli df oraz root du -x wskazują na to samo, przyczyną nie jest usunięty plik. Pozostałe przyczyny mają inny charakter i każda z nich wymaga odrębnej weryfikacji.

Wyczerpanie inodów przy dostępnym miejscu na dysku

Inode przechowuje metadane pojedynczego pliku. System plików ext4 tworzy stałą liczbę inodów podczas formatowania, dlatego może dojść do sytuacji, w której system plików wyczerpie pulę inodów, mimo dostępnego miejsca w blokach danych. Tworzenie nowych plików kończy się wtedy niepowodzeniem, nawet jeśli df -h wskazuje na wolną przestrzeń.

df -h /
df -i /

Pierwsze polecenie zlicza bloki, a drugie inody. Należy porównać kolumnę użycia dla każdego z nich. Niskie zużycie bloków przy maksymalnym wykorzystaniu inodów oznacza, że przyczyną problemu jest bardzo duża liczba bardzo małych plików.

df odrzuca -i oraz --output w tym samym wywołaniu, więc jeśli potrzebne są surowe liczby do odczytu lub przekazania do innego polecenia, należy wybrać pola inodów po nazwie i pominąć -i.

df --output=itotal,iused,iavail,ipcent /

Kolumny te zawierają te same dane rozliczeniowe, które wyświetla df -i, w formie umożliwiającej łatwe przetwarzanie.

Zlokalizuj pliki, zliczając wpisy zamiast bajtów.

sudo du --inodes -x -d 1 / 2>/dev/null | sort -rn | head

Powtórz to samo polecenie o jeden poziom niżej w katalogu, który wykazał największą liczbę plików, aż do dotarcia do drzewa katalogów generującego te pliki. Jeśli używana wersja du nie obsługuje --inodes, polecenie sudo find /var -xdev -type f | wc -l przeliczy poddrzewo w wolniejszy sposób.

Rozwiązaniem jest usunięcie lub przeniesienie tych plików. Nie można zwiększyć liczby inodów w istniejącym systemie plików ext4, ponieważ ich liczba jest ustalana w czasie mkfs, więc zwiększenie tej wartości wymaga odtworzenia systemu plików i przywrócenia danych z kopii zapasowej. XFS przydziela inody dynamicznie w miarę potrzeb, więc nie napotyka takiego sztywnego ograniczenia. Maszyna z kontenerami osiąga oba limity szybciej niż inne, ponieważ warstwy obrazów zawierają wiele małych plików. Na takiej maszynie czyszczenie użycia dysku przez Docker na VPS jest właściwym rozwiązaniem, które odzyskuje znacznie więcej miejsca niż ogólne czyszczenie systemu plików.

Przestrzeń ukryta pod punktem montowania

Katalog może zawierać pliki przed zamontowaniem w nim czegokolwiek. Po zamontowaniu systemu plików w takim katalogu, znajdujące się w nim pliki pozostają na swoim miejscu: nadal zajmują przestrzeń, są uwzględniane przez df, ale nie można uzyskać do nich dostępu za pomocą nazwy. du nie widzi tych plików, ponieważ punkt montowania je przesłania.

Można to zademonstrować przy użyciu tmpfs, który nie wymaga wolnego miejsca na dysku. Ta część wymaga maszyny z uprawnieniami do montowania, więc zadziała na VPS typu KVM.

sudo mkdir -p /srv/covered
sudo cp /etc/services /srv/covered/
ls /srv/covered
sudo mount -t tmpfs tmpfs /srv/covered
ls /srv/covered
sudo umount /srv/covered
ls /srv/covered

Środkowe polecenie ls pokazuje pusty katalog. Kopia nigdzie nie zniknęła: nadal znajduje się w głównym systemie plików i powraca w momencie odmontowania. Należy wyobrazić sobie usługę, która zapisywała logi w tej ścieżce przez miesiąc, zanim ktoś zamontował tam wolumen.

Aby odnaleźć rzeczywistą zawartość na działającym serwerze, należy zamontować główny system plików po raz drugi w innym miejscu. Montowanie typu bind pokazuje system plików bez zamontowanych wewnątrz niego innych systemów plików.

sudo mkdir -p /mnt/rootcheck
sudo mount --bind / /mnt/rootcheck
sudo du -xhs /mnt/rootcheck/* 2>/dev/null | sort -h
sudo umount /mnt/rootcheck

Wszystko, co pojawia się na tej liście, a nie jest widoczne w standardowej ścieżce, znajduje się pod punktem montowania. Po zakończeniu pracy należy odmontować bind mount, w przeciwnym razie późniejsze du bez flagi -x policzy te same pliki dwukrotnie.

Bloki zarezerwowane dla użytkownika root

System plików ext4 rezerwuje część bloków dla użytkownika root, aby zapełnienie dysku nie uniemożliwiło logowania się i naprawy systemu. Proces działający z uprawnieniami zwykłego użytkownika napotka błąd zapisu wcześniej, podczas gdy df nadal będzie wskazywać niewielką ilość wolnego miejsca. Należy sprawdzić bieżące ustawienie dla danego systemu plików, zamiast zakładać wartości domyślne.

dev=$(df --output=source / | tail -n 1)
sudo tune2fs -l "$dev" | grep -i 'block count'

Polecenie to wyświetla całkowitą liczbę bloków oraz liczbę bloków zarezerwowanych w tych samych jednostkach, co pozwala na bezpośrednie wyliczenie proporcji. df raportuje kolumnę available jako przestrzeń dostępną dla zwykłego użytkownika, dlatego suma użytego i dostępnego miejsca jest mniejsza niż całkowity rozmiar partycji. Różnica stanowi rezerwę.

Wartość tę można zmienić za pomocą sudo tune2fs -m <percent> "$dev". Zmiana jest stosowana natychmiastowo i nie wymaga ponownego montowania systemu plików. Zmniejszenie rezerwy na oddzielnym systemie plików z danymi jest uzasadnione. W przypadku głównego systemu plików (root) należy pozostawić wystarczającą ilość miejsca, aby użytkownik root mógł prowadzić zapis, ponieważ całkowicie zapełniony system plików root jest znacznie trudniejszy w naprawie. tune2fs działa w systemach ext2, ext3 oraz ext4. System XFS nie posiada odpowiednika tego ustawienia.

Kiedy polecenie du wprowadza w błąd

Cztery nawyki du generują sumy, które wydają się błędne.

  • Twarde dowiązania: du zlicza i-węzeł tylko raz, nawet jeśli wskazuje na niego kilka nazw, dlatego drzewo pełne twardych dowiązań raportuje wartość mniejszą niż suma rozmiarów plików.
  • Pliki rzadkie (sparse files): du raportuje faktycznie przydzielone bloki, podczas gdy ls -l raportuje rozmiar pozorny. Należy dodać flagę --apparent-size, aby zobaczyć drugą wartość.
  • Uprawnienia: przy uruchomieniu przez zwykłego użytkownika du pomija pliki, których nie może odczytać, co prowadzi do zaniżonych wyników. Wyświetlane błędy są często przekierowywane do /dev/null, przez co użytkownicy przestają je analizować.
  • Granice systemu plików: bez użycia -x, du / zlicza każdy system plików zamontowany poniżej /, więc suma może przekroczyć wartość raportowaną przez df /.

df posiada również jeden nawyk, który warto znać. Raportuje każdy system plików oddzielnie, dlatego należy uruchomić go dla konkretnej ścieżki, której dotyczy problem z zapisem. Osobna partycja /boot zapełnia się w swoim własnym tempie wraz z gromadzeniem się pakietów jądra, a usuwanie starych jąder w systemie Ubuntu jest zadaniem odrębnym od zwalniania miejsca na /.

Procedura postępowania w przypadku rzeczywistego incydentu

  1. Uruchom df -h <path> oraz df -i <path> na systemie plików, którego dotyczył nieudany zapis, zamiast odruchowo sprawdzać /.
  2. Uruchom sudo du -xh -d 1 <mountpoint> 2>/dev/null | sort -h, a następnie przejdź do największego katalogu.
  3. Jeśli du nie potrafi wskazać przyczyny zajętości miejsca raportowanej przez df, przeszukaj /proc pod kątem usuniętych plików, które nadal pozostają otwarte.
  4. Jeśli oba narzędzia wskazują to samo, wykonaj bind mount systemu plików w innej lokalizacji i sprawdź, czy wewnątrz punktu montowania nie znajdują się ukryte pliki.
  5. Jeśli limit wyczerpują inody, należy liczyć liczbę plików, a nie ich rozmiar w bajtach.

Każdy z powyższych kroków wykorzystuje polecenie, którego wynik można odczytać. Na tym polega różnica między naprawą usterki a zgadywaniem jej przyczyny.

FAQ

Dlaczego df pokazuje, że dysk jest pełny, podczas gdy du wskazuje na znacznie mniejsze zajęcie?

Najczęstszą przyczyną jest plik, który został usunięty, podczas gdy proces nadal go utrzymuje jako otwarty. Usunięcie pliku usuwa jego wpis w katalogu, więc du nie znajduje nazwy do przeszukania i przestaje go uwzględniać w obliczeniach. Inode oraz przypisane do niego bloki pozostają zajęte do momentu zamknięcia ostatniego deskryptora, a df zlicza wszystkie zajęte bloki. Należy przeszukać /proc/<pid>/fd pod kątem dowiązań symbolicznych, których cel jest oznaczony jako usunięty; w ten sposób można zidentyfikować zarówno plik, jak i proces, który go przetrzymuje. Przed uznaniem porównania za wiarygodne należy upewnić się, że polecenie du zostało uruchomione jako root z flagą -x, ponieważ zwykły użytkownik pomija bez ostrzeżenia katalogi, do których nie ma uprawnień odczytu.

Jak znaleźć usunięty plik, który jest nadal otwarty, bez użycia lsof?

Należy skorzystać z rejestru otwartych deskryptorów prowadzonego przez jądro systemu. sudo find /proc/[0-9]*/fd -lname '*(deleted)' -printf '%p -> %l\n' 2>/dev/null wyświetla listę wszystkich deskryptorów wskazujących na plik, który nie posiada nazwy, a identyfikator procesu (PID) znajduje się w ścieżce, którą wypisuje to polecenie. sudo stat -Lc %s na jednej z tych ścieżek deskryptorów zwraca rozmiar pliku, co pozwala na ich posortowanie i wybranie właściwego. Metoda ta nie wymaga instalacji żadnych dodatkowych pakietów, co jest istotne w sytuacjach, gdy instalacja oprogramowania na systemie plików bez wolnego miejsca kończy się niepowodzeniem.

Czy można zwolnić miejsce bez przerywania procesu?

Czasami jest to możliwe. sudo truncate -s 0 /proc/<pid>/fd/<n> uzyskuje dostęp do tego samego inode poprzez deskryptor i zwalnia jego bloki, podczas gdy proces nadal działa. Jest to rozwiązanie najbezpieczniejsze, gdy proces otworzył plik w trybie dopisywania (append mode), ponieważ operacje zapisu zawsze trafiają na koniec pliku. Jeśli proces nie działał w tym trybie, przesunięcie zapisu (write offset) pozostaje w poprzednim miejscu, a kolejna operacja zapisu odtwarza plik z luką na początku. W efekcie zgłaszany rozmiar wraca do poprzedniej wartości, podczas gdy bloki pod luką pozostają wolne. Rozwiązaniem, które nie pozostawia plików rzadkich (sparse files), jest restart jednostki lub wysłanie sygnału wymuszającego ponowne otwarcie logów, zgodnie z dokumentacją danej usługi.

df pokazuje wolne miejsce, ale zapis nadal kończy się błędem. Co może być przyczyną?

Należy sprawdzić liczbę wolnych inode za pomocą df -i dla danej ścieżki, ponieważ system plików z wolnymi blokami, ale bez wolnych inode, odrzuca tworzenie nowych plików. Należy sprawdzić, czy zapis jest wykonywany przez użytkownika innego niż root na systemie plików ext4, gdzie pozostały jedynie bloki zarezerwowane, co można zweryfikować za pomocą sudo tune2fs -l na danym urządzeniu. Należy również upewnić się, że sprawdzany jest system plików, do którego faktycznie kierowany jest zapis, ponieważ oddzielne /boot lub /var zapełniają się niezależnie od /.

Dlaczego du raportuje większą sumę niż df?

du bez flagi -x przechodzi przez wszystkie systemy plików zamontowane w podanej ścieżce, sumując zajętość wielu systemów plików, podczas gdy df opisuje tylko jeden. Montowania typu bind pogarszają ten problem, ponieważ te same pliki są zliczane wielokrotnie w każdej ścieżce, w której się pojawiają. Należy dodać -x, aby ograniczyć du do jednego systemu plików, oraz wskazać df tę samą ścieżkę, aby oba polecenia opisywały ten sam zakres danych.