Ответ 1
IIRC, bash не налагает ограничение на количество данных, которое может хранить переменная. Однако он ограничен средой, в которой выполнялось bash. См. этот ответ для более полного объяснения.
Предположим, что у меня есть оболочка script, в которой есть оператор вроде:
a=$(find / -type f)
Это говорит о том, что существует определенный список файлов с файловыми путями, которые будут храниться в переменной 'a'.
Каков максимальный предел или количество строк, которые он может хранить. Как его найти?
IIRC, bash не налагает ограничение на количество данных, которое может хранить переменная. Однако он ограничен средой, в которой выполнялось bash. См. этот ответ для более полного объяснения.
В качестве отправной точки я попробовал следующий скрипт в OS X 10.10.5, используя встроенную утилиту bash на Macbook Pro Retina с процессором Intel Core i7 с частотой 2,8 ГГц:
#!/bin/bash
humombo="X"
while true; do
humombo="$humombo$humombo"
echo "Time $(date "+%H:%M:%S"), chars $(echo "$humombo" | wc -c)"
done
Результаты: размер снова и снова удваивается (обратите внимание, что размеры включают дополнительный байт для конца одной строки). Вещи начали замедляться, когда humombo
прошел 4MB; удвоение с 256 МБ до 512 МБ заняло 48 секунд, и сценарий взорвался после этого:
mbpe:~ griscom$ ./delme.sh
Time 16:00:04, chars 3
Time 16:00:04, chars 5
Time 16:00:04, chars 9
Time 16:00:04, chars 17
Time 16:00:04, chars 33
Time 16:00:04, chars 65
Time 16:00:04, chars 129
Time 16:00:04, chars 257
Time 16:00:04, chars 513
Time 16:00:04, chars 1025
Time 16:00:04, chars 2049
Time 16:00:04, chars 4097
Time 16:00:04, chars 8193
Time 16:00:04, chars 16385
Time 16:00:04, chars 32769
Time 16:00:04, chars 65537
Time 16:00:04, chars 131073
Time 16:00:04, chars 262145
Time 16:00:04, chars 524289
Time 16:00:04, chars 1048577
Time 16:00:04, chars 2097153
Time 16:00:05, chars 4194305
Time 16:00:05, chars 8388609
Time 16:00:07, chars 16777217
Time 16:00:09, chars 33554433
Time 16:00:15, chars 67108865
Time 16:00:27, chars 134217729
Time 16:00:51, chars 268435457
Time 16:01:39, chars 536870913
bash(80722,0x7fff77bff300) malloc: *** mach_vm_map(size=18446744071562072064) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
./delme.sh: xrealloc: cannot allocate 18446744071562068096 bytes
mbpe:~ griscom$
Две заметки:
Я подозреваю, что сбой был больше, потому что весь процесс занял слишком много памяти, а не достиг предела единственной переменной емкости.
Играя с этим, я выполнял те же команды в интерактивном режиме, и когда выход из цикла завершился, bash был прерван; Я должен был открыть новое окно терминала, чтобы сделать что-нибудь. Таким образом, слишком большое выделение памяти нарушает работу bash неизвестными способами; Я предполагаю, что выполнение этого в сценарии очищается при выходе.
Изменить: я только что попробовал тот же код на мощной системе Ubuntu 18:
Time 18:03:02, chars 3
Time 18:03:02, chars 5
Time 18:03:02, chars 9
Time 18:03:02, chars 17
Time 18:03:02, chars 33
Time 18:03:02, chars 65
Time 18:03:02, chars 129
Time 18:03:02, chars 257
Time 18:03:02, chars 513
Time 18:03:02, chars 1025
Time 18:03:02, chars 2049
Time 18:03:02, chars 4097
Time 18:03:02, chars 8193
Time 18:03:02, chars 16385
Time 18:03:02, chars 32769
Time 18:03:02, chars 65537
Time 18:03:02, chars 131073
Time 18:03:02, chars 262145
Time 18:03:02, chars 524289
Time 18:03:02, chars 1048577
Time 18:03:02, chars 2097153
Time 18:03:02, chars 4194305
Time 18:03:02, chars 8388609
Time 18:03:03, chars 16777217
Time 18:03:04, chars 33554433
Time 18:03:07, chars 67108865
Time 18:03:12, chars 134217729
Time 18:03:23, chars 268435457
Time 18:03:43, chars 536870913
./delme.sh: xrealloc: cannot allocate 18446744071562068096 bytes
На это ушло меньше половины времени, и он умер немного чище, но с тем же размером символов. (Кстати, число в сообщении об ошибке, десятичное 18446744071562068096, равно 0xffff ffff 8000 0080, поэтому очевидно, что здесь мы достигаем некоторых ограничений по количеству.)
Я не думаю, что существует ограничение на размер переменной в bash, но вам действительно нужна переменная 6 ГБ в вашей оболочке (suject to ulimit -a
, конечно)?
Конечно, в командной строке есть предел. grep <pattern> $TEN_MILLION_FILENAMES
не будет работать. На самом деле очень сложно выполнить любую команду, не создавную с помощью $TEN_MILLION_FILES
. Вам нужны другие стратегии, такие как выполнение этого для каждого каталога, или временные файлы & c.
Как я знаю, единственный способ найти предел - это эмпирически. Попробуйте запустить следующую оболочку script и дождитесь окончания:
limit=1
while true
do
limit=`echo 1+$limit|bc`
a=' '$a
echo $limit
done
Насколько я вижу, стандарт не налагает никаких ограничений. Но базовая система может. Я вспоминаю, что однажды я столкнулся с лимитом на какой-то AIX.
Вы можете проверить, как configure проверяет максимальное количество аргументов - попробуйте, пока не найдете ошибку. Какой-то итерационный подход с формулой var(i)=concatenation(var(i-1),var(i-1))
. Рано или поздно вы достигли предела (по крайней мере, предел памяти при обработке).
Небольшое улучшение сценария Дэниела Грискома:
ПРИМЕЧАНИЕ: строка "VmPeak" будет иметь пустой вывод при запуске скрипта внутри Cygwin, так как cygwin не полностью реплицирует /proc (в основном значение "VmPeak" отсутствует, но вы можете перейти к "VmSize", возможно, в таком случае?)
$ cat delme.sh
#!/bin/zsh
humombo="X"
pid=$$
while true; do
humombo="$humombo$humombo"
echo "Time $(date "+%H:%M:%S"), chars $(echo "$humombo" | wc -c)"
echo -n "Memory usage: "
grep ^VmPeak /proc/${pid}/status
done