Командний рядок Bash та ліміт введення


90

Чи існує якесь обмеження символів, встановлене в bash (або інших оболонках), як довго може бути введення? Якщо так, то який обмеження символів?

Тобто чи можна написати команду в bash, яка занадто довга для виконання командного рядка? Якщо немає необхідного ліміту, чи є запропонований ліміт?


2
Обмеження вводу сильно відрізняється від обмеження аргументів на рівні ОС (зауважте, що деякі речі, крім аргументів, такі як змінні середовища, також застосовуються до цього). Створена команда, передана операційній системі, може мати більше або менше символів, ніж команда оболонки, яка її генерувала.
Чарльз Даффі

Відповіді:


127

Обмеження довжини командного рядка встановлюється не оболонкою, а операційною системою. Зазвичай ця межа знаходиться в межах ста кілобайт. POSIX позначає це обмеження, ARG_MAXі в системах, що відповідають POSIX, ви можете запитувати його

$ getconf ARG_MAX    # Get argument limit in bytes

Наприклад, на Cygwin це 32000, а на різних BSD та системах Linux, якими я користуюся, це десь від 131072 до 2621440.

Якщо вам потрібно обробити список файлів, що перевищують це обмеження, можливо, ви захочете переглянути xargsпрограму, яка неодноразово викликає програму з підмножиною аргументів, що не перевищує ARG_MAX.

Так, щоб відповісти на ваше конкретне запитання, можна спробувати запустити команду із занадто довгим списком аргументів. В оболонці буде повідомлення про помилку "Список аргументів занадто довгий".

Зверніть увагу, що вхід до програми (як прочитано на stdin або будь-якому іншому дескрипторі файлу) не обмежений (лише доступними ресурсами програми). Отже, якщо ваш скрипт оболонки читає рядок у змінну, ви не обмежені ARG_MAX. Обмеження також не поширюється на вбудовані корпуси.


Чудова відповідь, але я хотів би пояснити. Якби я отримав конструкцію, cmd <<< "$LONG_VAR"і значення LONG_VAR перевищило межу, чи не підірвало б це мою команду?
Кшиштоф Яблонський

1
@ KrzysztofJabłoński Навряд чи, оскільки вміст LONG_VARпередається на stdin - і це робиться повністю в оболонці; він не розширений як аргумент cmd, тому обмеження ARG_MAX для fork () / exec () не вступає в дію. Спробувати самостійно легко: створіть змінну із вмістом, що перевищує ARG_MAX, і запустіть свою команду.
Йенс

2
Ось роз'яснення, для запису: для файлу m4a 8 мегабайт, я зробив: blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null. Зверніть увагу, що помилки немає.
Mike S

3
Невелике застереження. Змінні середовища також враховуються. sysconf manpage > Важко використовувати ARG_MAX, оскільки не вказано, скільки> простору аргументів для exec (3) споживається змінними середовища користувача>.
Герріт

3
@ user188737 Я відчуваю, що це досить велике застереження у ПОМИЛКАХ . Наприклад xargsна MacOS 10.12.6 межах , скільки він намагається поставити в один exec()до ARG_MAX - 4096. Отже, сценарії, що використовуються, xargsможуть працювати, доки одного разу хтось не помістить занадто багато речей у середовище. Натрапляючи на це зараз (обійдіть це за допомогою xargs -s ???:).
neuralmer

44

Гаразд, жителі. Тож я вже досить довго приймаю обмеження довжини командного рядка як євангелію. Отже, що робити з припущеннями? Природно - перевірити їх.

У моєму розпорядженні машина Fedora 22 (мається на увазі: Linux з bash4). Я створив каталог із 500 000 індексів (файлів), кожен із 18 символів. Довжина командного рядка становить 9 500 000 символів. Створений таким чином:

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

І ми зазначаємо:

$ getconf ARG_MAX
2097152

Однак зверніть увагу, що я можу зробити це:

$ echo * > /dev/null

Але це не вдається:

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

Я можу запустити цикл for:

$ for f in *; do :; done

що є ще однією вбудованою оболонкою.

Уважне читання документації щодоARG_MAX станів, максимальна довжина аргументу для функцій exec . Це означає: Без дзвінка execнемає ARG_MAXобмежень. Тож це пояснювало б, чому вбудовані оболонки не обмежені ARG_MAX.

І справді, я можу lsстворити каталог, якщо мій список аргументів становить 109948 файлів або близько 2089 000 символів (дайте чи візьміть). Однак, як тільки я додаю ще один файл із 18-символьним іменем файлу, тоді з’являється занадто довга помилка списку аргументів . Так ARG_MAXпрацює як рекламуються: ехес зазнає невдачі з більш ARG_MAXсимволів на аргументі list- в тому числі, слід зазначити, дані навколишнє середовище.


Хм Я не читав існуючу відповідь, щоб сказати, що вбудовані об'єкти підпадають під обмеження, про які йдеться, але я, звичайно, бачу, як хтось міг.
Чарльз Даффі

6
Так, я думаю, що важко пам'ятати - особливо для нових службовців командного рядка, - що ситуація виклику bash builtin проти fork / exec'ing команди відрізняється неочевидними способами. Я хотів це пояснити. Одне питання, яке я незмінно отримую на співбесіді (як Linux Sysadmin), це: "Отже, я отримав купу файлів у каталозі. Як я прокручую їх усі ..." Допитувач незмінно рухається до лінії обмеження довжини і хоче знайти / в той час чи рішення xargs. Надалі я збираюся сказати: "ах, просто використовуй цикл for. Він може це впоратись!" :-)
Mike S

@MikeS, хоча ви могли б зробити цикл for, якщо ви можете використовувати комбінований файл find-xargs, ви будете розгалужуватись набагато менше і будете швидшими. ;-)
Лестер Чунг

4
@LesterCheung for f in *; do echo $f; doneвзагалі не буде розгалужуватися (усі вбудовані). Тому я не знаю, що комбінація find-xargs буде швидшою; це не перевірено. Справді, я не знаю, в чому полягає проблема OP. Можливо, find /path/to/directoryце не буде йому корисно, оскільки це поверне ім'я шляху до файлу. Можливо, йому подобається простота for f in *циклу. Незважаючи на це, розмова стосується обмеження лінійного введення - не ефективності. Тож давайте залишимося на темі, яка стосується довжини командного рядка.
Mike S

FWIW, проблема, як я пам'ятаю, полягала в тому, що я просто намагався написати оболонку на мові C і визначити, як довго я повинен дозволяти введенням.
Дерек Халден

-3

Існує обмеження буфера приблизно на 1024. Зчитування просто зависає в середині вставки або введення. Для вирішення цієї проблеми використовуйте опцію -e.

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

-e використовуйте Readline для отримання рядка в інтерактивній оболонці

Змініть прочитане на читання -e, і дратівливе зависання рядка зникає.


1
Йдеться не про read: "Тобто чи можна написати команду в bash, яка занадто довга для виконання командного рядка?"
Чай Т. Рекс,

@ ChaiT.Rex ви начебто правильні, але ось у чому річ: спробуйте запустити Bash інтерактивно без Readline, тобто bash --noediting, а в новому echo somereallylongwordзапиті спробуйте запустити команду , де дійсно довге слово довше 4090 символів. Спробоване в Ubuntu 18.04, слово обрізане, тому, очевидно, воно має щось спільне з тим, що Readline не ввімкнено.
Амір

@Amir Цікаво! Ви праві! Я спробував відредагувати відповідь, але потім зрозумів, що параметр -e не застосовується до bash в цьому контексті (у bash він негайно виходить із оболонки при помилці). І я не впевнений, чому Пол намагався читати. У будь-якому випадку, обмеження буфера становить 4-5000 символів, коли bash запускається за допомогою --noreadline. Це побічний ефект, про який я не знав і не очікував.
Mike S,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.