“ Lista argumentów jest zbyt długa ”: Jak sobie z tym poradzić bez zmiany polecenia?

Po uruchomieniu polecenia, takiego jak ls */*/*/*/*.jpg, pojawia się błąd

-bash: /bin/ls: Argument list too long 

Wiem, dlaczego tak się dzieje: dzieje się tak, ponieważ istnieje ograniczenie jądra dotyczące ilości miejsca na argumenty polecenia. Standardową radą jest zmiana polecenia, którego używam, aby uniknąć wymagania tak dużej ilości miejsca na argumenty (np. Użyj find i xargs).

A jeśli nie chcę zmieniać polecenia? Co jeśli chcę nadal używać tego samego polecenia? Jak sprawić, by wszystko „po prostu działało” bez wyświetlania tego błędu? Jakie rozwiązania są dostępne?

Komentarze

  • Przydatna lektura: Bash FAQ 95 . Bez zmiany polecenia tam ' niewiele możesz zrobić poza rekompilacją w celu zwiększenia maksymalnego rozmiaru listy argumentów lub zmianą struktury katalogów, aby było mniej plików.
  • @ jw013 w oparciu o wersję jądra Linuksa może być możliwe zwiększenie listy argumentów – zobacz unix.stackexchange.com/a/45161/8979 , aby uzyskać szczegółowe informacje o zmianie ostatnie systemy.
  • @UlrichDangel, tak, jest to możliwe! Zobacz moją odpowiedź; moja odpowiedź pokazuje, jak to zrobić (na L inux, z najnowszym jądrem).

Odpowiedź

W systemie Linux maksymalna ilość miejsca na polecenia argumenty to 1/4 dostępnego miejsca na stosie. Więc rozwiązaniem jest zwiększenie ilości miejsca dostępnego na stosie.

Krótka wersja: uruchom coś takiego jak

ulimit -s 65536 

Dłuższa wersja : Domyślna ilość miejsca dostępnego dla stosu to około 8192 KB. Możesz zobaczyć ilość dostępnego miejsca w następujący sposób:

$ ulimit -s 8192 

Wybierz większą liczbę i ustaw ilość dostępnego miejsca dla stosu. Na przykład, jeśli chcesz dopuścić do 65536 KB na stos, uruchom to:

$ ulimit -s 65536 

Być może będziesz musiał się zastanowić, jak duże to potrzeba być, używając metody prób i błędów. W wielu przypadkach jest to szybkie i brudne rozwiązanie, które eliminuje konieczność modyfikowania polecenia i wypracowania składni find, xargs itd. (chociaż zdaję sobie sprawę, że ma to inne zalety).

Uważam, że jest to specyficzne dla Linuksa. Podejrzewam, że prawdopodobnie nie pomoże w żadnym innym systemie operacyjnym Unix (nie testowano).

Komentarze

  • Możesz sprawdzić, czy zadziałało : $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
  • Czy to oznacza, że jeśli ustawię nieograniczony rozmiar stosu za pomocą ulimit -s unlimited, rozmiar wiersza poleceń będzie też bez ograniczeń?

Odpowiedz

Zamiast ls */*/*/*/*.jpg, spróbuj:

echo */*/*/*/*.jpg | xargs ls 

xargs (1) wie, jaka jest maksymalna liczba argumentów w systemie i podzieli swoje standardowe wejście, aby wywołać określony wiersz poleceń wiele razy bez większej liczby argumentów niż ten limit, cokolwiek to jest (możesz również ustawić go poniżej maksymalnego poziomu systemu operacyjnego za pomocą -n opcja).

Załóżmy na przykład, że limit to 3 argumenty i masz pięć plików. W takim przypadku xargs wykona ls dwukrotnie:

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

Często jest to idealne rozwiązanie, ale nie zawsze – na przykład nie można polegaj na ls (1) sortowaniu wszystkich wpisów poprawnie, ponieważ każdy osobny ls -invocation posortuje tylko podzbiór wpisów nadany mu przez xargs.

Chociaż możesz zwiększyć limit zgodnie z sugestiami innych, nadal będzie istniał limit – i któregoś dnia Twoja kolekcja JPG znów ją przerośnie. Powinieneś przygotować swoje skrypty do obsługi nieskończonej liczby …

Komentarze

  • Dziękujemy za pomysł! To nie jest złe obejście. Dwa ostrzeżenia: 1. To psuje katalogi i nazwy plików, które mają spacje w nazwie, więc ' nie jest idealnym zamiennikiem. 2. Czy będzie to ten sam problem z Argument list too long, ale dla echo zamiast ls, w powłokach, w których echo nie jest poleceniem wbudowanym powłoki? (Może to ' nie jest problemem w większości powłok, więc może to ' jest nieistotne.)
  • Tak , problemy ze znakami specjalnymi w nazwach plików. Najlepiej jest użyć find z predykatem -print0 – i przesłać jego dane wyjściowe do xargs z opcją -0.echo to wbudowana powłoka, która nie podlega ograniczeniom wiersza poleceń exec (3).
  • Działa to z poleceniami, które oczekują argumentu zmiennej jako ostatniego parametru, na przykład ls, ale co mam zrobić, gdy chcę mv wiele plików do jednego katalogu, np mv * destdir? Jeśli * daje " za dużo argumentów " błąd, mogę ' t spraw, aby xargs przekazały ścieżki jako pierwsze w mv, czy mogę? / li>
  • Sprawdź stronę podręcznika pod kątem xargs w twoim systemie – na przykład we FreeBSD pomoże -J ty z tym zadaniem. Jeśli w Twoim systemie operacyjnym nie ma sposobu, aby to zrobić, ' będziesz musiał napisać niestandardowy skrypt, aby zmienić kolejność argumentów. Na przykład: destdir=$1; shift; mv "$@" "$destdir". Następnie przekaż ten nowy skrypt do xargs: .... | xargs newscript $destdir

Answer

Ten artykuł na temat Linux Journal zawiera 4 rozwiązania. Tylko czwarte rozwiązanie nie wymaga zmiany polecenia:

Metoda nr 4 polega na ręcznym zwiększeniu liczby stron przydzielonych w jądrze dla wiersza poleceń argumenty. Jeśli spojrzysz na plik include / linux / binfmts.h, u góry znajdziesz następujące informacje:

/* * MAX_ARG_PAGES defines the number of pages allocated for arguments * and envelope for the new program. 32 should suffice, this gives * a maximum env+arg of 128kB w/4KB pages! */ #define MAX_ARG_PAGES 32 

Aby zwiększyć ilość pamięci poświęcony argumentom wiersza poleceń, wystarczy podać wartość MAX_ARG_PAGES z większą liczbą. Gdy ta edycja zostanie zapisana, po prostu przekompiluj, zainstaluj i zrestartuj do nowego jądra tak, jak robisz to zwykle.

Na moim własnym systemie testowym udało mi się rozwiązać wszystkie moje problemy, podnosząc tę wartość do 64. Po rozległych testowania, nie miałem ani jednego problemu od momentu przełączenia. Jest to całkowicie oczekiwane, ponieważ nawet przy MAX_ARG_PAGES ustawionym na 64, najdłuższy możliwy wiersz poleceń, jaki mogłem wygenerować, zajmowałby tylko 256 KB pamięci systemowej – niewiele jak na dzisiejsze standardy sprzętowe systemu .

Zalety metody nr 4 są oczywiste. Teraz możesz po prostu uruchomić polecenie w normalny sposób i zakończy się ono pomyślnie. Wady są równie jasne. Jeśli zwiększysz ilość dostępnej pamięci do wiersza poleceń poza ilość dostępnej pamięci systemowej, możesz stworzyć atak DOS na swój własny system i spowodować jego awarię. W szczególności w systemach z wieloma użytkownikami nawet niewielki wzrost może mieć znaczący wpływ, ponieważ każdemu użytkownikowi przydzielane jest wtedy dodatkową pamięć. Dlatego zawsze przeprowadzaj obszerne testy w swoim własnym środowisku, ponieważ jest to najbezpieczniejszy sposób określenia, czy metoda nr 4 jest dla Ciebie realną opcją.

Zgadzam się, że to ograniczenie jest bardzo irytujące.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *