Обычно оболочки различают переменные и функции, потому что они используются в разных контекстах. В двух словах, имя является именем переменной, если оно появляется после $
или в качестве аргумента встроенных функций, таких какexport
(без-f
)иunset
(без-f
). Имя является именем функции, если оно появляется как команда (после раскрытия псевдонима )или как аргумент для export -f
, unset -f
и т. д.
Переменные можно экспортировать в среду. Имя переменной среды такое же, как и у переменной оболочки (, и значения такие же ).
Bash, в отличие от большинства других оболочек, также может экспортировать функции в среду. Поскольку в среде нет индикации типа, нет никакого способа узнать, является ли запись в среде функцией или нет, кроме как путем анализа имени или значения переменной среды.
Старые версии bash хранили функцию в среде, используя имя функции в качестве имени и что-то похожее на определение функции в качестве значения функции. Например:
bash-4.1$ foobar () { echo foobar; }
bash-4.1$ export -f foobar
bash-4.1$ env |grep -A1 foobar
foobar=() { echo foobar
}
bash-4.1$
Обратите внимание, что невозможно отличить функцию с кодом { echo foobar; }
от переменной со значением () { echo foobar}
(, где 
— символ новой строки ). Это оказалось неудачным дизайнерским решением.
Иногда сценарии оболочки вызываются с переменными среды, значение которых находится под контролем потенциально враждебной сущности. Например, CGI-скрипты. Функция экспорта/импорта функций Bash позволяла вводить функции таким образом. Например, выполнение скрипта
#!/bin/bash
ls
из удаленного запроса безопасен, если среда не содержит переменных с определенным именем (, напримерPATH
). Но если запрос может установить переменную среды ls
в () { cat /etc/passwd; }
, тогда bash с радостью выполнит cat /etc/passwd
, поскольку это тело функции ls
.
Эта уязвимость системы безопасности была обнаружена Стефаном Шазела как один из аспектов ошибки Shellshock . В версиях bash после -Shellshock экспортированные функции идентифицируются по имени , а не по содержимому.
bash-4.3$ foobar () { echo foobar; }
bash-4.3$ export -f foobar
bash-4.3$ env |grep -A1 foobar
BASH_FUNC_foobar%%=() { echo foobar
}
Теперь нет проблем с безопасностью, потому что такие имена, как BASH_FUNC_foobar%%
, обычно не используются в качестве имен команд и могут быть отфильтрованы интерфейсами, которые позволяют передавать переменные среды.Технически возможно иметь символ %
в имени переменной окружения (, это то, что заставляет работать экспортируемые функции современного bash ), но обычно люди этого не делают, потому что оболочки не принимают %
в имя переменной.
Предложение в руководстве bash относится к старому поведению (до -Shellshock ). Его следует обновить или удалить. В современных версиях bash в среде нет двусмысленности, если вы предполагаете, что переменные среды не будут иметь имя, оканчивающееся на %%
.
Само ядро не накладывает никаких ограничений на значение file-max
, кроме того, которое накладывается его типом (unsigned long
, поэтому 4 294 967 295 на типичных 32 -битных системах и 18 446 744 073 709 551 615 на типичных 64 -битных системах. системы ).
Однако каждый открытый файл занимает около одного килобайта памяти , поэтому вы будете ограничены объемом установленной физической оперативной памяти; десять миллионов открытых файлов заняли бы примерно десять гигабайт памяти. Ядро инициализирует file-max
до 10% используемой памяти при загрузке, что означает, что «жесткий» предел для любой данной системы примерно в десять раз превышает значение по умолчанию.