Linux环境变量名称中允许使用的字符


143

Linux环境变量名称中允许使用哪些字符?我对手册页和网络的粗略搜索只产生了有关如何使用变量的信息,但没有产生允许使用的名称。

我有一个Java程序,它需要一个包含点的已定义环境变量,例如com.example.fancyproperty。使用Windows,我可以设置该变量,但是我没有在Linux中设置它的运气(在SuSE和Ubuntu中尝试过)。甚至允许使用该变量名吗?


3
幸运的是,我发现该程序对Java系统属性(使用-D命令行选项声明)同样满意,因此现在可以运行了。显然,程序没有告诉我这两个变量集。但是我仍然对允许使用哪些环境变量名称感到好奇。
Christian Semrau 2010年

@AleksandrDubinsky我删除了它。这是类似的,但有关别名定义不完全是环境变量stackoverflow.com/questions/24690640/...
石灰

1
如果您使用的是Spring,则默认的SystemEnvironmentPropertySource还将查找com_example_fancypropertyCOM_EXAMPLE_FANCYPROPERTY
Aleksandr Dubinsky

Answers:


203

来自公开组

这些字符串的形式为name = value; 名称中不得包含字符“ =”。对于在符合IEEE Std 1003.1-2001的系统之间可移植的值,该值应由来自便携式字符集的字符组成(NUL除外,如下所示)。

因此,名称可以包含除=和NUL之外的任何字符,但是:

IEEE Std 1003.1-2001的Shell and Utilities卷中的实用程序使用的环境变量名称仅由大写字母,数字和可移植字符集中定义的字符中的'_'(下划线)组成,并且不能以数字开头。实现可能允许其他字符;申请应容忍此类名称的存在。

因此,尽管名称可能是有效的,但您的外壳可能不支持字母,数字和下划线以外的任何内容。


8
只是检查:第二个引号是非规范性的:它只是观察到POSIX定义为其实用程序特殊的变量[a-zA-Z_][a-zA-Z0-9_]*(隐式表示此形式更聪明),但是实际的规范(引号1)要求所有实现都支持除=NUL
Ciro Santilli郝海东冠状病六四事件法轮功2014年

3
另外,“便携式字符集” pubs.opengroup.org/onlinepubs/000095399/basedefs/…包含空格和非可打印字符之类的东西:那么我们可以使用这些东西吗?
Ciro Santilli郝海东冠状病六四事件法轮功

3
这正是我观察到的。Shell不喜欢将特殊字符用作变量名的一部分。但是,当一个程序或脚本(例如Java或Perl)使用名称中带有特殊字符的变量初始化并调用另一个可执行文件(子进程)时,后者可执行文件可以毫无问题地访问该变量。
oᴉɹǝɥɔ

1
@checksum,为变量名显式指定了UPPERCASE,对POSIX指定的工具(包括shell)具有含义;具有至少一个小写字符的名称被明确保留供应用程序使用。因此,最佳实践实际上是在应用程序的变量名中至少包含一个小写字符,以确保您不会无意间被覆盖(因为设置shell变量将覆盖任何同名的环境变量)系统。见pubs.opengroup.org/onlinepubs/9699919799/basedefs/...
查尔斯·杜菲

2
@CiroSantilli乌坎事件2016六四事件法轮功,您可以在环境变量中使用它们;您不能在shell变量中使用它们,并且不能保证可以从shell中访问这些环境变量。
Charles Duffy

37

IEEE Std 1003.1-2008 / IEEE POSIX P1003.2 / ISO 9945.2 Shell and Tools标准的Shells部分上的POSIX标准 没有定义变量名称的词汇约定,但是粗略地 查看源代码发现它使用了类似于

[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:/ *准确定义合法的shell标识符组成。* / #define legal_variable_starter(c)(ISALPHA(c)||(c ==' '))#define legal_variable_char(c)(ISALNUM(c)|| c ==' ')
克里斯2010年

3
您不需要在第一个字符类中使用该加号。
2014年

2
@scravy是正确的,尽管我从源头获取了正则表达式,所以我要保留+。–
Aiden Bell

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

Shell部分中没有,但绝对有POSIX标准,其中包括环境变量命名的约定(并实际上讨论了保留供Shell使用的名称)。见pubs.opengroup.org/onlinepubs/9699919799/basedefs/...
查尔斯·杜菲

12

我的快速测试表明,它们基本上遵循与C变量名称相同的规则,即

  1. az,AZ _和0-9
  2. 不能以数字开头

因此,这排除了.它们内部。任何非法变量名都记入unknown command

这已在ZSH中进行了测试,该产品大多数与BASH兼容。


6

取决于“允许”的含义。

忽略Windows随机数:

环境是一个字符串数组,传递给程序的主要功能。如果您阅读execve(2),除了空终止之外,您将看不到对这些字符串的任何要求或限制。

按照约定,每个字符串都由NAME = value组成。没有引号约定,因此在该约定中名称中不能包含“ =”。

正常人通过与外壳讨论它们来设置这些字符串。每个shell对于有效的变量NAME都有自己的想法,因此您必须阅读shell的手册页以了解其想法。

通常,诸如com.baseball.spit = fleagh之类的东西是Java系统属性,并且不管某些Java程序是否愿意使用该环境,最好使用-D来指定它们。


我早该得出的结论是,变量的格式类似于Java系统属性,而不是尝试将其设置为环境变量。
Christian Semrau 2010年


4

是的,您可以做到。

使用execenv命令实施此场景。

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. Shell调用内置exec
  2. Shell内置exec调用syscall.exec创建进程“ env”以替换当前的Shell
  3. env进程调用syscall.execvp创建进程'/ bin / sh'来替换env进程

其他方式

  • Docker镜像

如果使用docker,则可以在Dockerfile中设置变量

FROM busybox
ENV xx.f%^&*()$#ff=1234
  • Kubernetes配置图

如果您使用的是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

尽管大多数shell不允许设置环境变量(如其他答案所述),但如果需要,您可以使用使用非标准环境变量执行其他程序env(1)

例如,擦除所有环境并将其设置Strange.Env:Var为value foo,然后执行将其打印的perl程序:

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

将打印

$VAR1 = {
          'Strange.Env:Var' => 'foo'
        };
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.