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

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

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

105575 次浏览

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

  1. A-Z _和0-9
  2. 不能以数字开头

所以这里面排除了 .。任何非法的变量名都被归入 unknown command

这是在 ZSH 进行的测试,该国基本上与 BASH 兼容。

这取决于外壳。我猜您默认使用 bash,在这种情况下允许使用字母、数字和下划线,但是不能以数字开始变量名。从 Bash 诉第3节开始 在变量名中不允许使用句点

那要看你说的“允许”是什么意思了。

暂时忽略 Windows:

环境是一个字符串数组,传递给程序的 main 函数。如果您读取 Execve (2) ,您将看到除了空终止之外,对这些字符串没有任何要求或限制。

按照约定,每个字符串由 NAME = value 组成。没有引号约定,所以在这个约定中名称中不能有’=’。

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

一般来说,像 com.baseball.spay = fleagh 这样的东西是 Java 系统属性,不管某些 Java 程序是否愿意回到环境中,最好使用-D 来指定它们。

来自 公开组:

这些字符串的形式 Name = value; < strong > 名称不应包含 字符’=’. 用于值为 便携式跨系统,符合 根据 IEEE 标准1003.1-2001, 由字符组成 可移植字符集(< strong > ,NUL 除外 如下所示

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

环境变量中的实用程序使用的名称 美国电气电子工程师协会公用事业量 1003.1-2001仅由大写字母、数字和“ _”组成 (下划线) 来自字符 在便携式字符集 < strong > 和 不要以数字 开头 字符可由 实施; 容忍这些名字的存在。

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

的 shell 部分的 POSIX 标准 IEEE Std 1003.1-2008/IEEE POSIX P1003.2/ISO 9945.2 Shell 和 Tools 标准没有为变量名定义词法约定,但是只是粗略地定义了一下 查看源代码 可以发现它使用了类似于

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

(编辑: 在第2个字符类中添加缺少的下划线。)

一个简单的说明,因为一些 shell 不支持 + in regex,所以一个可能更加便携的 regex 可能是:

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

虽然大多数 shell 不允许设置环境变量(正如在其他答案中提到的) ,但是如果需要,可以使用 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'
};

是的,你能做到。

使用 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验证环境变量

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

输出为 happy-variable-name

发生什么事了?

  1. 外壳呼叫内置执行
  2. Shell 内置 exec 调用 syscall.exec 创建进程‘ env’以替换当前 Shell
  3. Env 进程调用 syscall.Execvp create process’/bin/sh’来替换 env 进程

另一种方式

  • 码头形象

如果你使用 docker,你可以在 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 允许“-”、“ _”或“”

当用 systemctl edit <service_name>编辑 system service vars 时,我可以使用除 " = \ $之外的所有符号,比如:

[Service]
Environment="TOKEN=~'+*^,j-;H@[J;;G,g&xG:eH)RfK@I&fjjgdZ|IXKm]-[C"

而且没有任何问题。