Який максимальний розмір значення змінної середовища?


83

Чи існує обмеження кількості даних, які можна зберігати у змінній середовища в Linux, і якщо так: що це?

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


Фактичний ліміт на вікна становить 31 767. Ви читали про setкоманду, яка має обмеження до 8191 символу в командному рядку. Див. Цю статтю msdn , проте все-таки випадкове обмеження.
Крістофер Керренс,

5
8191 не такий вже й випадковий. Зараз 2 ^ 13 - 1.
Барнабі Доусон,

AWS Lambda: загальний розмір набору [змінних середовища] не перевищує 4 КБ ( джерело )
Мартін Тома,

1
@BarnabyDawson, можливо, Крістофер мав на увазі це у тому сенсі, що це було довільно?
0xC0000022L

Відповіді:


75

Я не думаю, що в Linux існує обмеження змінної для кожного середовища. Загальний розмір усіх змінних середовища, взятих разом, обмежений у execve()часі. Див. "Обмеження розміру аргументів та середовища" тут для отримання додаткової інформації.

Процес може використовувати setenv()або putenv()вирощувати довкілля поза початковим простором, виділеним виконавцем.

Ось швидка і брудна програма, яка створює змінну середовища на 256 МБ.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    size_t size = 1 << 28; /* 256 MB */
    char *var;

    var = malloc(size);
    if (var == NULL) {
        perror("malloc");
        return 1;
    }

    memset(var, 'X', size);
    var[size - 1] = '\0';
    var[0] = 'A';
    var[1] = '=';

    if (putenv(var) != 0) {
        perror("putenv");
        return 1;
    }

/*  Demonstrate E2BIG failure explained by paxdiablo */
    execl("/bin/true", "true", (char *)NULL);
    perror("execl");   


    printf("A=%s\n", getenv("A"));

    return 0;
}

5
+1 для інформації execve (). Ви можете фактично додати змінні середовища до (принаймні) 8M, але виклики exec () не працюватимуть. Це проявляється у bash як "список аргументів занадто довгий" щоразу, коли ви намагаєтесь виконати команду.
paxdiablo

1
Також зверніть увагу, що POSIX вимагає, щоб ARG_MAX був принаймні _POSIX_ARG_MAX, який повинен бути 4096.
ninjalj

10
Найкраща відповідь (від Chipaca) на askUbuntu обговорює використання, xargs --show-limitsщоб отримати більше інформації.
DocSalvager

Я також бачу обмеження на рядок аргументу - "Крім того, обмеження на рядок становить 32 сторінки (константа ядра MAX_ARG_STRLEN)"
kiran01bm

24

Ну, це принаймні 4M на моїй коробці. У той момент я нудьгував і блукав. Сподіваюся, вихід терміналу буде закінчений до того, як я повернусь на роботу в понеділок :-)

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 зробило це трохи простішим, але я думав, що це може не вдатися до того, як я досяг позначки 4М. Це життя.
paxdiablo


@ LưuVĩnhPhúc: оскільки програми мають обмеження. Це можуть бути довільні обмеження або вони можуть базуватися на наявних ресурсах, але обмеження існують. Цілком можливо, DavidK припускав, що його оболонку не використовуватимуть (
не-) зловмисники,

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

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)переповнює. Все дуже приємно, але ми, звичайно, далеко за будь-яким розумним обмеженням тут ...
cyberbird

3

Ось дві корисні команди:

  • getconf -a |grep MAX

  • true | xargs --show-limits


Яка із ~ 100 змінних є релевантною? Де вони задокументовані?
ingomueller.net

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-код (нижче), модифікуючи його для різних значень, і виявив, що він працює для змінної довжини до 128k. Після цього з якихось причин це не працює; не виникає жодних винятків, не повідомляється про помилку, але значення не відображається в підкорінці.

Можливо, це обмеження, специфічне для 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)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.