Linia poleceń Bash i limit wprowadzania

90

Czy istnieje jakiś limit znaków narzucony w bashu (lub innych powłokach) na jak długo może trwać wejście? Jeśli tak, jaki jest ten limit znaków?

To znaczy czy można napisać polecenie w bash, które jest zbyt długie, aby wiersz poleceń mógł zostać wykonany? Jeśli nie ma wymaganego limitu, czy istnieje sugerowany limit?

Derek Halden
źródło
2
Wejście granica jest bardzo różni się od argumentu OS poziomu limitu (zauważ, że pewne rzeczy, inne niż argumentów, takich jak zmienne środowiskowe, mają zastosowanie również do tej jednej). Wygenerowane polecenie przekazane do systemu operacyjnego może mieć więcej lub mniej znaków niż polecenie powłoki, które je wygenerowało.
Charles Duffy

Odpowiedzi:

126

Limit długości wiersza poleceń nie jest narzucony przez powłokę, ale przez system operacyjny. Limit ten zwykle mieści się w zakresie stu kilobajtów. POSIX oznacza to ograniczenie, ARG_MAXa w systemach zgodnych z POSIX można o nie zapytać

$ getconf ARG_MAX    # Get argument limit in bytes

Np. Na Cygwin jest to 32000, a na różnych BSD i systemach Linux, których używam, wynosi od 131072 do 2621440.

Jeśli potrzebujesz przetworzyć listę plików przekraczającą ten limit, możesz przyjrzeć się xargsnarzędziu, które wielokrotnie wywołuje program z podzbiorem argumentów nieprzekraczającym ARG_MAX.

Odpowiadając na twoje konkretne pytanie, tak, można spróbować uruchomić polecenie ze zbyt długą listą argumentów. Powłoka wyświetli komunikat o błędzie „lista argumentów jest zbyt długa”.

Zauważ, że dane wejściowe do programu (czytane na stdin lub jakimkolwiek innym deskryptorze pliku) nie są ograniczone (tylko przez dostępne zasoby programu). Więc jeśli twój skrypt powłoki wczytuje łańcuch do zmiennej, nie jesteś ograniczony przez ARG_MAX. To ograniczenie nie dotyczy również poleceń wbudowanych powłoki.

Jens
źródło
Dobra odpowiedź, ale chciałbym wyjaśnić. Jeśli cmd <<< "$LONG_VAR"otrzymam konstrukcję, a wartość LONG_VAR przekroczy limit, czy zepsułoby to moje polecenie?
Krzysztof Jabłoński
1
@ KrzysztofJabłoński Mało prawdopodobne, bo zawartość LONG_VARjest przekazywana na stdin - i to w całości odbywa się w shellu; nie jest cmdinterpretowany jako argument do , więc limit ARG_MAX dla fork () / exec () nie wchodzi w grę. Łatwo jest spróbować samemu: utwórz zmienną o zawartości przekraczającej ARG_MAX i uruchom polecenie.
Jens
2
Poniżej znajduje się wyjaśnienie, dla przypomnienia: w pliku m4a 8 megabajtów, zrobiłem: blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null. Uwaga bez błędu.
Mike S
3
Małe zastrzeżenie. Liczą się również zmienne środowiskowe. sysconf manpage > Trudno jest używać ARG_MAX, ponieważ nie określono, ile> przestrzeni argumentów dla exec (3) jest zużywane przez zmienne środowiskowe> użytkownika.
Gerrit,
3
@ user188737 Czuję, że jest to dość duże zastrzeżenie w BŁĘDACH . Na przykład xargsna MacOS 10.12.6 limitów ile próbuje umieścić w jednym exec()z ARG_MAX - 4096. Tak więc używanie skryptów xargsmoże działać, aż pewnego dnia ktoś umieści za dużo rzeczy w środowisku. Wchodzę w to teraz (obejdź to:) xargs -s ???.
neuralmer
44

Ok, mieszkańcy. Tak więc od dłuższego czasu akceptuję ograniczenia długości wiersza poleceń jako gospel. Co więc zrobić ze swoimi założeniami? Oczywiście - sprawdź je.

Mam do dyspozycji maszynę Fedora 22 (czyli: Linux z bash4). Utworzyłem katalog zawierający 500 000 i-węzłów (plików), każdy o długości 18 znaków. Długość wiersza poleceń wynosi 9500000 znaków. Utworzono w ten sposób:

seq 1 500000 | while read digit; do
    touch $(printf "abigfilename%06d\n" $digit);
done

I zauważamy:

$ getconf ARG_MAX
2097152

Pamiętaj jednak, że mogę to zrobić:

$ echo * > /dev/null

Ale to się nie udaje:

$ /bin/echo * > /dev/null
bash: /bin/echo: Argument list too long

Mogę uruchomić pętlę for:

$ for f in *; do :; done

czyli kolejna wbudowana powłoka.

Uważne czytanie dokumentacjiARG_MAX stanów. Maksymalna długość argumentów funkcji exec . To znaczy: bez dzwonienia execnie ma ARG_MAXograniczeń. To wyjaśniałoby, dlaczego polecenia wbudowane powłoki nie są ograniczone przez ARG_MAX.

I rzeczywiście, mogę lsmój katalog, jeśli moja lista argumentów ma 109948 plików lub około 2089000 znaków (daj lub weź). Jednak gdy dodam jeszcze jeden 18-znakowy plik nazwy pliku, pojawia się zbyt długi błąd listy argumentów . Tak więc ARG_MAXdziała zgodnie z zapowiedzią: wykonanie kończy się niepowodzeniem z więcej niż ARG_MAXznakami na liście argumentów - w tym, należy zauważyć, danymi środowiska.

Mike S.
źródło
Hmm. Nie przeczytałem istniejącej odpowiedzi, aby zasugerować, że elementy wbudowane podlegają przedmiotowemu ograniczeniu, ale z pewnością widzę, jak ktoś mógłby to zrobić.
Charles Duffy
6
Tak, myślę, że trudno jest zapamiętać - szczególnie dla nowszych entuzjastów wiersza poleceń - że sytuacja wywołania polecenia wbudowanego basha a rozwidlenia / wykonania polecenia jest inna w nieoczywisty sposób. Chciałem to wyjaśnić. Jedno pytanie, które niezmiennie otrzymuję podczas rozmowy kwalifikacyjnej (jako administrator systemu Linux), brzmi: „Więc mam kilka plików w katalogu. Jak mam je wszystkie zapętlić ...” Pytający niezmiennie jedzie w kierunku linii limit długości i chce znaleźć / podczas gdy lub xargs. W przyszłości powiem: „ach, do diabła - po prostu użyj pętli for. Poradzi sobie z tym!” :-)
Mike S
@MikeS Chociaż możesz zrobić pętlę for, jeśli możesz użyć kombinacji find-xargs, rozwidlisz znacznie mniej i będziesz szybszy. ;-)
Lester Cheung
4
@LesterCheung w for f in *; do echo $f; doneogóle nie rozwidla (wszystkie wbudowane). Więc nie wiem, czy combo find-xargs będzie szybsze; nie został przetestowany. Rzeczywiście, nie wiem, jaki jest zestaw problemów PO. Może mu się find /path/to/directoryto nie przyda, ponieważ zwróci ścieżkę do pliku. Może lubi prostotę for f in *pętli. Niezależnie od tego, rozmowa dotyczy ograniczenia wejścia liniowego, a nie wydajności. Pozostańmy więc przy temacie, który dotyczy długości wiersza poleceń.
Mike S
FWIW, problem, o ile pamiętam, polegał na tym, że próbowałem napisać powłokę w C i określić, jak długo powinienem pozwolić na wprowadzanie danych.
Derek Halden
-3

Istnieje ograniczenie bufora około 1024. Odczyt po prostu zawiesi się w trakcie wklejania lub wprowadzania. Aby rozwiązać ten problem, użyj opcji -e.

http://linuxcommand.org/lc3_man_pages/readh.html

-e użyj Readline, aby uzyskać wiersz w powłoce interaktywnej

Zmień odczyt na -e i irytujące zawieszanie się linii znika.

Paul Kenjora
źródło
1
Tu nie chodzi o read: „Czy jest możliwe napisanie w bashu polecenia, które jest zbyt długie, aby wiersz poleceń mógł zostać wykonany?”
Chai T. Rex
@ ChaiT.Rex masz trochę racji, ale o to chodzi: spróbuj uruchomić Bash w sposób interaktywny bez Readline, tj. bash --noediting, A po nowym echo somereallylongwordznaku zachęty spróbuj uruchomić polecenie , w którym niektóre wszystkie słowa są dłuższe niż 4090 znaków. Wypróbowane na Ubuntu 18.04, słowo zostało obcięte, więc oczywiście ma to coś wspólnego z wyłączeniem Readline.
Amir
@Amir Ciekawe! Masz rację! Próbowałem edytować odpowiedź, ale potem zdałem sobie sprawę, że opcja -e nie ma zastosowania do basha w tym kontekście (w bashu, kończy powłokę natychmiast po błędzie). I nie jestem pewien, dlaczego Paul odwrócił się, żeby przeczytać. W każdym razie istnieje limit bufora wynoszący 4-5000 znaków, gdy bash jest uruchamiany z opcją --noreadline. To efekt uboczny, o którym nie wiedziałem lub nie spodziewałem się.
Mike S