Allowed characters in Linux environment variable names
From The Open Group:
These strings have the form name=value; names shall not contain the character '='. For values to be portable across systems conforming to IEEE Std 1003.1-2001, the value shall be composed of characters from the portable character set (except NUL and as indicated below).
So names may contain any character except = and NUL, but:
Environment variable names used by the utilities in the Shell and Utilities volume of IEEE Std 1003.1-2001 consist solely of uppercase letters, digits, and the '_' (underscore) from the characters defined in Portable Character Set and do not begin with a digit. Other characters may be permitted by an implementation; applications shall tolerate the presence of such names.
So while the names may be valid, your shell might not support anything besides letters, numbers, and underscores.
The POSIX standards on shells section of IEEE Std 1003.1-2008 / IEEE POSIX P1003.2/ISO 9945.2 Shell and Tools standard doesn't define the lexical convention for variable names, however a cursory look at the source reveals it uses something similar to
[a-zA-Z_]+[a-zA-Z0-9_]*
(Edit: Added missing underscore in 2nd character class.)
A quick note, as some shells don't support the + in regex, a potentially more portable regex may be:
[a-zA-Z_]{1,}[a-zA-Z0-9_]{0,}
My quick testing showed that they basically follow the same rules as C variable names do have, namely
- a-z, A-Z,
_
and 0-9 - May NOT begin with a number
So this excludes .
inside them. Any illegal variable name is credited with unknown command
.
This was tested in ZSH, which is mostly BASH-compatible.
YES, YOU CAN DO IT.
Use exec
and env
command to implement this scene.
Test Fixture in Docker
docker run -it --rm alpine:3.10
Run command in container:
exec env spring.application_name=happy-variable-name ${SHELL:-/bin/sh}
Verify environment variables:
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=/
Use ps aux
to verify PID not changed
PID USER TIME COMMAND
1 root 0:00 /bin/sh
12 root 0:00 ps aux
Use python
to verify environemnt variable
apk add python
python -c 'import os; print(os.environ["spring.application_name"])'
OUTPUT is happy-variable-name
.
What happen?
- Shell call builtin exec
- Shell builtin exec call syscall.exec create process 'env' to replace current shell
- env process call syscall.execvp create process '/bin/sh' to replace env process
Another way
- Docker image
If you are using docker, you can set variable in Dockerfile
FROM busybox
ENV xx.f%^&*()$#ff=1234
- Kubernetes configmap
If you are using kubernetes, you can set variable by 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
Deploy pod kubectl apply -f test.yaml
Verify kubectl logs foobar
output:
xx.ff-bar=1234
ConfigMap allow '-', '_' or '.'