Каков максимальный размер значения переменной среды?


85

Есть ли ограничение на объем данных, которые могут храниться в переменной среды в Linux, и если да, то что это такое?

Для Windows я нашел следующую статью базы знаний, которая резюмирует: Windows XP или новее: 8191 символ Windows 2000 / NT 4.0: 2047 символов


Фактический лимит для окон - 31 767. Вы читали о setкоманде, у которой ограничение в командной строке составляет 8191 символ. См. Эту статью msdn Тем не менее, это случайное ограничение.
Кристофер Карренс,

5
8191 не такой уж и случайный. Это 2 ^
Барнаби Доусон

AWS Lambda: общий размер набора [переменных среды] не превышает 4 КБ ( источник )
Мартин Тома

1
@BarnabyDawson, возможно, Кристофер имел в виду это в том смысле, что это было произвольно?
0xC0000022L 04

Ответы:


77

Я не думаю, что в Linux есть ограничение на переменную среды. Общий размер всех вместе взятых переменных среды ограничен по execve()времени. См. «Ограничения размера аргументов и среды» здесь для получения дополнительной информации.

Процесс может использовать setenv()или putenv()расширять среду за пределы начального пространства, выделенного exec.

Вот быстрая и грязная программа, которая создает переменную среды 256 МБ.


5
+1 для информации execve (). Фактически вы можете добавить переменные среды до (как минимум) 8M, но вызовы exec () не будут работать. В bash это проявляется как «слишком длинный список аргументов» всякий раз, когда вы затем пытаетесь запустить команду.
paxdiablo

1
Также обратите внимание, что POSIX требует, чтобы ARG_MAX был не менее _POSIX_ARG_MAX, который должен быть
4096.

10
В верхнем ответе (от Chipaca) на askUbuntu обсуждается использование xargs --show-limitsдля получения дополнительной информации.
DocSalvager

Я также вижу ограничение на строку аргумента - «Кроме того, ограничение на строку составляет 32 страницы (константа ядра MAX_ARG_STRLEN)»
kiran01bm

24

Ну у меня на коробке минимум 4М. В этот момент мне стало скучно, и я ушел. Надеюсь, вывод терминала будет завершен до того, как я вернусь на работу в понедельник :-)

export b1=A
export b2=$b1$b1
export b4=$b2$b2
export b8=$b4$b4
export b16=$b8$b8
export b32=$b16$b16
export b64=$b32$b32
export b128=$b64$b64
export b256=$b128$b128
export b512=$b256$b256
export b1k=$b512$b512
export b2k=$b1k$b1k
export b4k=$b2k$b2k
export b8k=$b4k$b4k
export b16k=$b8k$b8k
export b32k=$b16k$b16k
export b64k=$b32k$b32k
export b128k=$b64k$b64k
export b256k=$b128k$b128k
export b512k=$b256k$b256k
export b1m=$b512k$b512k
export b2m=$b1m$b1m
export b4m=$b2m$b2m
echo $b4m
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
:    :    :    :    :    :    :    :    :    :    :    :
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Если вы беспокоитесь, что 4M может быть недостаточно для вашей переменной среды, вы можете переосмыслить, как вы что-то делаете.

Возможно, было бы лучше поместить информацию в файл, а затем использовать переменную среды для ссылки на этот файл. Я видел случаи, когда, если переменная имеет форму @/path/to/any/fspec, она получает фактическую информацию из файла path/to/any/fspec. Если он не начинается с @, он использует значение самой переменной среды.


Достаточно интересно, что при установке всех этих переменных каждая отдельная команда начинает жаловаться на то, что список аргументов слишком длинный, поэтому, даже если он позволяет вам их устанавливать, он может не иметь возможности запускать программы после того, как вы это сделали (поскольку он должен передать среду этим программам).


1
Надеюсь, вы использовали сценарий, а не печатали все вручную!
Крис Хуанг-Ливер,

2
Нет, отсюда и "надоедает" немного. Редактирование командной строки в режиме Vi сделало это немного проще, но я подумал, что он может выйти из строя, прежде чем я достигну отметки 4M. Такова жизнь.
paxdiablo


@ LưuVĩnhPhúc: потому что у программ есть ограничения. Это могут быть произвольные ограничения или они могут основываться на доступных ресурсах, но ограничения существуют. Вполне возможно, DavidK предположил, что его панцирь не будет (неправильно) использован сумасшедшими, которым следует знать лучше :-)
paxdiablo

7

Я провел быстрый тест на своем Linux-компьютере со следующим фрагментом:

a="1"
while true
do
    a=$a$a
    echo "$(date) $(numfmt --to=iec-i --suffix=B --padding=7 ${#a})" 
done

На моем компьютере (Gentoo 3.17.8-gentoo-r1) это приводит к (последние строки вывода):

Wed Jan  3 12:16:10 CET 2018   16MiB
Wed Jan  3 12:16:11 CET 2018   32MiB
Wed Jan  3 12:16:12 CET 2018   64MiB
Wed Jan  3 12:16:15 CET 2018  128MiB
Wed Jan  3 12:16:21 CET 2018  256MiB
Wed Jan  3 12:16:33 CET 2018  512MiB
xrealloc: cannot allocate 18446744071562068096 bytes

Итак: предел достаточно высокий!


1
18446744071562068096 байт составляет около 15 эксабайт. :) Это похоже на большой скачок с 512 МБ.
Маркус

1
@Marcus: это ... Я предполагаю, что как-то 1Гб, то есть 1073741824 байта, т.е. 2 ^ 30 байтов где-то переполняется. Количество байтов в ошибке 18446744071562068096 довольно близко к 2 ^ 64, то есть 18446744073709551616
cyberbird

1
У меня ограниченные навыки C / gdb, но я думаю, что проблема в исходном файле bash subst.c. Функция sub_append_string (строка 726) использует переменную int со знаком, называемую n, для вычисления нового размера. Новый размер (2 ^ 31) подойдет, но есть расчет выравнивания: n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE); и я подозреваю, что часть: (n + DEFAULT_ARRAY_SIZE)переполнена. Все очень хорошо, но мы,
конечно же, вышли

3

Вот две полезные команды:

  • getconf -a |grep MAX

  • true | xargs --show-limits


Какая из ~ 100 переменных актуальна? Где они задокументированы?
ingomueller.net 02

1

Точно не знаю, но быстрый эксперимент показывает, что ошибок не возникает, например, при значении 64 КБ:

% perl -e 'print "#include <stdlib.h>\nint main() { return setenv(\"FOO\", \"", "x"x65536, "\", 1); }\n";'\
| gcc -x c -o envtest - && ./envtest && echo $?
0

1

Я использовал этот очень быстрый и грязный php-код (ниже), изменив его для разных значений, и обнаружил, что он работает для переменной длины до 128 КБ. После этого по какой-то причине он не работает; исключение не возникает, ошибка не отображается, но значение не отображается в подоболочке.

Может, это ограничение для php? Может быть, есть настройки php.ini, которые могут на это повлиять? Или, может быть, есть ограничение на размер варов, которые наследует подоболочка? Может есть соответствующие настройки конфигурации ядра или оболочки ..

В любом случае, по умолчанию в CentOS ограничение на установку переменной окружения через putenv в php составляет около 128 КБ.

<?php

  $s = 'abcdefghijklmnop';
  $s2 = "";
  for ($i = 0; $i < 8100; $i++) $s2 .= $s;
  $result = putenv('FOO='.$s2);
  print shell_exec('echo \'FOO: \'${FOO}');
  print "length of s2: ".strlen($s2)."\n";
  print "result = $result\n";
?>

Информация о версии -

[root@localhost scratch]# php --version
PHP 5.2.6 (cli) (built: Dec  2 2008 16:32:08) 
<..snip..>

[root@localhost scratch]# uname -a
Linux localhost.localdomain 2.6.18-128.2.1.el5 #1 SMP Tue Jul 14 06:36:37 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

[root@localhost scratch]# cat /etc/redhat-release 
CentOS release 5.3 (Final)

0

Командная строка (со всеми аргументами) плюс переменная среды должны быть меньше 128 КБ.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.