Допустимые символы в именах переменных среды Linux

148

Какие символы разрешены в именах переменных среды Linux? Мой беглый поиск на страницах руководства и в Интернете дал только информацию о том, как работать с переменными, но не о том, какие имена разрешены.

У меня есть программа Java, для которой требуется определенная переменная среды, содержащая точку, например com.example.fancyproperty. В Windows я могу установить эту переменную, но мне не удалось установить ее в Linux (пробовал в SuSE и Ubuntu). Это имя переменной вообще разрешено?

Кристиан Семрау
источник
3
К счастью, я обнаружил, что программа так же довольна системным свойством Java (объявленным с параметром -Dкомандной строки), так что теперь она работает. Очевидно, программа просматривает оба набора переменных, не сообщая мне об этом. Но все же мне любопытно, какие имена переменных среды разрешены.
Кристиан Семрау
@AleksandrDubinsky Я удалил. Это похоже, но определение псевдонима - это не совсем переменные среды stackoverflow.com/questions/24690640/…
Lime
1
Если вы используете Spring , то по умолчанию SystemEnvironmentPropertySource также будет искать com_example_fancypropertyи COM_EXAMPLE_FANCYPROPERTY.
Александр Дубинский

Ответы:

210

От открытой группы :

Эти строки имеют вид имя = значение; Имена не должны содержать символа '='. Для значений, которые должны быть переносимы между системами, соответствующими стандарту IEEE Std 1003.1-2001, значение должно состоять из символов из переносимого набора символов ( кроме NUL и как указано ниже ).

Таким образом, имена могут содержать любой символ, кроме = и NUL, но:

Имена переменных среды, используемые утилитами в томе Shell and Utilities IEEE Std 1003.1-2001, состоят только из прописных букв, цифр и символа подчеркивания '_' из символов, определенных в Portable Character Set, и не начинаются с цифры. . Другие символы могут быть разрешены реализацией; приложения должны допускать наличие таких имен.

Таким образом, хотя имена могут быть действительными, ваша оболочка может не поддерживать ничего, кроме букв, цифр и подчеркиваний.

Роберт Гэмбл
источник
9
Просто проверяем: вторая цитата не является нормативной: она просто отмечает, что переменные, которые POSIX определяет как специальные для своих утилит, являются [a-zA-Z_][a-zA-Z0-9_]*(неявно предполагая, что эта форма более разумна), но фактическая спецификация (цитата 1) требует, чтобы вся реализация поддерживала что-либо, кроме =и NUL?
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
3
Кроме того, «переносимый набор символов» pubs.opengroup.org/onlinepubs/000095399/basedefs/… содержит такие вещи, как пробелы и непечатаемые элементы : можем ли мы использовать эти вещи или нет?
Чиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
3
Это именно то, что я наблюдаю. Shell не любит специальные символы как часть имени переменной. Однако когда одна программа или сценарий (например, java или perl) инициализирует переменную со специальными символами в ее имени и вызывает другой исполняемый файл (дочерний процесс), последний исполняемый файл может получить доступ к этой переменной без проблем.
oᴉɹǝɥɔ
1
@checksum, UPPERCASE явно указывается для имен переменных, имеющих значение для инструментов, указанных в POSIX, включая оболочку; имена, содержащие хотя бы один символ нижнего регистра, явно зарезервированы для использования приложением. Таким образом, лучшая практика состоит в том, чтобы фактически включать по крайней мере один символ нижнего регистра в имена переменных ваших приложений, чтобы гарантировать, что вы случайно не перезаписываете (поскольку установка переменной оболочки перезапишет любую переменную среды с одинаковым именем) переменную со значением система. См. Pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Чарльз Даффи,
2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, вы можете использовать их в переменных окружения; Вы не можете использовать их в скорлупе переменных, и эти переменные окружения не гарантируется быть доступны из оболочки.
Чарльз Даффи,
38

Стандарты POSIX в разделе оболочек IEEE Std 1003.1-2008 / IEEE POSIX P1003.2 / ISO 9945.2 Стандарт Shell и Tools не определяет лексическое соглашение для имен переменных, однако беглый взгляд на источник показывает, что он использует что-то похожее на

[a-zA-Z_]+[a-zA-Z0-9_]*

(Изменить: добавлено недостающее подчеркивание во втором классе символов.)

Небольшое примечание, поскольку некоторые оболочки не поддерживают + в регулярном выражении, потенциально более переносимым регулярным выражением может быть:

[a-zA-Z_]{1,}[a-zA-Z0-9_]{0,}

Эйден Белл
источник
4
Спасибо, Эйден. Я думаю, что во втором наборе квадратных скобок отсутствует подчеркивание: Вероятно, его следует читать: [a-zA-Z_][a-zA-Z0-9_]* Для тех, кто, как я, находит ссылку на bash-4.1 немного расплывчатой ​​(616 000 строк кода), вот несколько советов по найдите соответствующие строки кода: subst.c: param_expand(), in the default case-> general.h:/ * Точно определите, из чего состоит допустимый идентификатор оболочки. * / #define legal_variable_starter (c) (ISALPHA (c) || ​​(c == ' ')) #define legal_variable_char (c) (ISALNUM (c) || ​​c == ' ')
Крис
3
Вам не нужен этот плюс в первом классе символов.
scravy 03
2
@scravy правда, хотя я взял регулярное выражение из источника, поэтому я сохраню +.
Эйден Белл
4
POSIX определяет: 3.231 Имя a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit .
Не в разделе оболочки, но есть стандарты POSIX, которые включают соглашения об именах переменных среды (и фактически обсуждают имена, зарезервированные для использования оболочки). См. Pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Чарльз Даффи,
12

Мое быстрое тестирование показало, что они в основном следуют тем же правилам, что и имена переменных C, а именно:

  1. az, AZ _и 0–9
  2. НЕ МОЖЕТ начинаться с числа

Так что это исключает .внутри них. Присваивается любое недопустимое имя переменной unknown command.

Это было протестировано в ZSH, который в основном совместим с BASH.

ЛюкN
источник
6

Зависит от того, что вы подразумеваете под словом «разрешено».

Игнорирование Windows на время:

Окружение - это массив строк, переданный основной функции программы. Если вы прочитаете execve (2), вы не увидите никаких требований или ограничений для этих строк, кроме нулевого завершения.

По соглашению каждая строка состоит из NAME = value. Соглашения о кавычках не существует, поэтому вы не можете использовать знак «=» в имени в этом соглашении.

Нормальные люди задают эти условия, обсуждая их со своей оболочкой. У каждой оболочки есть свои представления о том, какие имена переменных являются допустимыми, поэтому вам нужно прочитать страницу руководства для текущей оболочки, чтобы узнать, что она думает.

Как правило, такие вещи, как com.baseball.spit = fleagh, являются свойствами системы Java, и независимо от того, готова ли какая-либо программа Java вернуться к среде, лучше указать их с помощью -D.

bmargulies
источник
Я должен был раньше прийти к выводу, что переменная отформатирована как системное свойство Java, вместо того, чтобы пытаться установить ее как переменную среды.
Christian Semrau
5

Это зависит от оболочки. Я предполагаю, что вы используете bash по умолчанию, и в этом случае буквы, цифры и символы подчеркивания разрешены, но вы не можете начинать имя переменной с числа. Начиная с Bash v.3, точки не допускаются в именах переменных .

ire_and_curses
источник
4

ДА, ТЫ МОЖЕШЬ СДЕЛАТЬ ЭТО.

Используйте execи envcommand для реализации этой сцены.

Тестовое приспособление в Docker

docker run -it --rm alpine:3.10

Запустить команду в контейнере:

exec env spring.application_name=happy-variable-name ${SHELL:-/bin/sh}

Проверьте переменные среды:

HOSTNAME=bd0bccfdc53b
SHLVL=2
HOME=/root
spring.application_name=happy-variable-name
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

Используйте ps auxдля проверки того, что PID не изменен

PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
   12 root      0:00 ps aux

Используйте pythonдля проверки переменной environemnt

apk add python
python -c 'import os; print(os.environ["spring.application_name"])'

ВЫХОД есть happy-variable-name.

Что случилось?

  1. Встроенный вызов оболочки exec
  2. Встроенный в оболочку exec вызов syscall.exec create process 'env' для замены текущей оболочки
  3. вызов процесса env syscall.execvp create process '/ bin / sh' для замены процесса env

По-другому

  • Образ докера

Если вы используете докер, вы можете установить переменную в Dockerfile

FROM busybox
ENV xx.f%^&*()$#ff=1234
  • Карта конфигурации Kubernetes

Если вы используете кубернеты, вы можете установить переменную с помощью ConfigMap

test.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: foo-config
data:
  "xx.ff-bar": "1234"

---
apiVersion: v1
kind: Pod
metadata:
  name: foobar
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "env" ]
      envFrom:
      - configMapRef:
          name: foo-config
  restartPolicy: Never

Развернуть модуль kubectl apply -f test.yaml

Проверить kubectl logs foobarвывод:

xx.ff-bar=1234

ConfigMap разрешает '-', '_' или '.'

Рьяный
источник
0

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

Например, стирание всего окружения и установка Strange.Env:Varзначения fooи выполнение программы perl, которая печатает это:

env -i Strange.Env:Var=foo perl -MData::Dumper -E 'say Dumper(\%ENV)'

напечатает

$VAR1 = {
          'Strange.Env:Var' => 'foo'
        };
Матия Налис
источник