Gibt es eine Art Zeichenbeschränkung in Bash (oder anderen Shells) für die Dauer einer Eingabe? Wenn ja, wie hoch ist diese Zeichenbeschränkung?
Dh Ist es möglich, einen Befehl in bash zu schreiben, der zu lang ist, um von der Befehlszeile ausgeführt zu werden? Wenn es kein erforderliches Limit gibt, gibt es ein vorgeschlagenes Limit?
bash
shell
unix
command-line-arguments
Derek Halden
quelle
quelle
Antworten:
Die Begrenzung für die Länge einer Befehlszeile wird nicht von der Shell, sondern vom Betriebssystem festgelegt. Diese Grenze liegt normalerweise im Bereich von hundert Kilobyte. POSIX bezeichnet diese Grenze
ARG_MAX
und auf POSIX-konformen Systemen können Sie sie abfragenAuf Cygwin sind dies beispielsweise 32000, und auf den verschiedenen BSDs und Linux-Systemen, die ich verwende, liegt der Wert zwischen 131072 und 2621440.
Wenn Sie eine Liste von Dateien verarbeiten müssen, die diese Grenze überschreiten, sollten Sie sich das
xargs
Dienstprogramm ansehen , das ein Programm wiederholt mit einer Teilmenge von Argumenten aufruft, die diese Grenze nicht überschreitenARG_MAX
.Um Ihre spezifische Frage zu beantworten, können Sie versuchen, einen Befehl mit einer zu langen Argumentliste auszuführen. Die Shell wird mit einer Meldung entlang "Argumentliste zu lang" fehlerhaft angezeigt.
Beachten Sie, dass die Eingabe in ein Programm (wie auf stdin oder einem anderen Dateideskriptor gelesen) nicht beschränkt ist (nur durch verfügbare Programmressourcen). Wenn Ihr Shell-Skript also eine Zeichenfolge in eine Variable einliest, sind Sie nicht durch eingeschränkt
ARG_MAX
. Die Einschränkung gilt auch nicht für Shell-Builtins.quelle
cmd <<< "$LONG_VAR"
und der LONG_VAR-Wert das Limit überschreiten würde, würde es meinen Befehl sprengen?LONG_VAR
stdin weitergegeben wird - und das ganz in der Shell; Es wird nicht als Argument für erweitertcmd
, sodass das ARG_MAX-Limit für fork () / exec () nicht ins Spiel kommt. Es ist ganz einfach, es selbst zu versuchen: Erstellen Sie eine Variable mit Inhalten, die ARG_MAX überschreiten, und führen Sie Ihren Befehl aus.blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null
. Beachten Sie keinen Fehler.xargs
macOS 10.12.6 wird beispielsweise begrenzt, wie viel versucht wird, in einsexec()
zu steckenARG_MAX - 4096
. Die Verwendung von Skriptenxargs
könnte also funktionieren, bis eines Tages jemand zu viel Material in die Umgebung bringt. Laufen Sie jetzt darauf (umgehen Sie es mit :)xargs -s ???
.Ok, Bürger. Daher habe ich die Grenzwerte für die Befehlszeilenlänge seit einiger Zeit als Evangelium akzeptiert. Was tun mit den eigenen Annahmen? Überprüfen Sie sie natürlich.
Ich habe eine Fedora 22-Maschine zur Verfügung (dh: Linux mit bash4). Ich habe ein Verzeichnis mit 500.000 Inodes (Dateien) mit jeweils 18 Zeichen erstellt. Die Befehlszeilenlänge beträgt 9.500.000 Zeichen. So erstellt:
Und wir stellen fest:
Beachten Sie jedoch, dass ich dies tun kann:
Dies schlägt jedoch fehl:
Ich kann eine for-Schleife ausführen:
Das ist eine andere Shell gebaut.
Sorgfältiges Lesen der Dokumentation für
ARG_MAX
Zustände, Maximale Argumentationsdauer für die exec-Funktionen . Das heißt: Ohne Anrufexec
gibt es keineARG_MAX
Einschränkung. Es würde also erklären, warum Shell-Buildins nicht durch eingeschränkt werdenARG_MAX
.Und tatsächlich kann ich
ls
mein Verzeichnis, wenn meine Argumentliste 109948 Dateien lang ist oder ungefähr 2.089.000 Zeichen (Geben oder Nehmen). Sobald ich jedoch eine weitere 18-stellige Dateinamensdatei hinzufüge, wird eine zu lange Fehlerliste angezeigt. SoARG_MAX
funktioniert wie in der Werbung: die exec mit mehr versagt alsARG_MAX
Zeichen auf dem Argumente Listen- einschließlich, sollte darauf hingewiesen werden, die Umgebungsdaten.quelle
for f in *; do echo $f; done
sich überhaupt nicht (alle eingebauten). Ich weiß also nicht, dass eine Find-Xargs-Kombination schneller sein wird. es wurde nicht getestet. In der Tat weiß ich nicht, was das Problem des OP ist. Vielleichtfind /path/to/directory
ist es für ihn nicht nützlich, weil es den Pfadnamen der Datei zurückgibt. Vielleicht mag er die Einfachheit einerfor f in *
Schleife. Unabhängig davon geht es im Gespräch um die Leitungseingangsgrenze und nicht um die Effizienz. Bleiben wir also beim Thema, das sich auf die Länge der Befehlszeile bezieht.Es gibt eine Puffergrenze von etwa 1024. Der Lesevorgang hängt einfach beim Einfügen oder bei der Eingabe. Um dies zu lösen, verwenden Sie die Option -e.
http://linuxcommand.org/lc3_man_pages/readh.html
-e Verwenden Sie Readline, um die Zeile in einer interaktiven Shell abzurufen
Ändern Sie Ihren Lesevorgang in "-e" und der störende Zeileneingang verschwindet.
quelle
read
: "Ist es möglich, einen Befehl in Bash zu schreiben, der zu lang ist, um von der Befehlszeile ausgeführt zu werden?"bash --noediting
, und versuchen Sie an der neuen Eingabeaufforderung, den Befehlecho somereallylongword
auszuführen, bei dem ein längeres Wort länger als 4090 Zeichen ist. Unter Ubuntu 18.04 wurde das Wort abgeschnitten, sodass es offensichtlich etwas damit zu tun hat, dass Readline nicht aktiviert ist.