Caracteres permitidos nos nomes de variáveis ​​de ambiente Linux

143

Quais caracteres são permitidos nos nomes de variáveis ​​de ambiente Linux? Minha pesquisa superficial das páginas de manual e da Web produziu apenas informações sobre como trabalhar com variáveis, mas não quais nomes são permitidos.

Eu tenho um programa Java que requer uma variável de ambiente definida contendo um ponto, como com.example.fancyproperty. No Windows, posso definir essa variável, mas não tive sorte em defini-la no linux (tentei no SuSE e no Ubuntu). Esse nome de variável é permitido?

Christian Semrau
fonte
3
Felizmente, descobri que o programa é tão feliz com uma propriedade do sistema Java (declarada com uma -Dopção de linha de comando), então funciona agora. Obviamente, o programa procura nos dois conjuntos de variáveis ​​sem me informar. Mas ainda estou curioso sobre quais nomes de variáveis ​​de ambiente são permitidos.
Christian Semrau
@AleksandrDubinsky eu o excluí. Isso é semelhante, mas a definição de alias não é exatamente variáveis ​​de ambiente stackoverflow.com/questions/24690640/…
Lime
1
Se você estiver usando o Spring , o SystemEnvironmentPropertySource padrão também procurará com_example_fancypropertye COM_EXAMPLE_FANCYPROPERTY.
Aleksandr Dubinsky

Respostas:

203

Do Grupo Aberto :

Essas seqüências têm o formato nome = valor; nomes não devem conter o caractere '='. Para que os valores sejam portáteis em sistemas em conformidade com IEEE Std 1003.1-2001, o valor deve ser composto por caracteres do conjunto de caracteres portáteis ( exceto NUL e conforme indicado abaixo ).

Portanto, os nomes podem conter qualquer caractere, exceto = e NUL, mas:

Os nomes de variáveis ​​de ambiente usados ​​pelos utilitários no volume Shell e Utilitários do IEEE Std 1003.1-2001 consistem apenas em letras maiúsculas, dígitos e o '_' (sublinhado) dos caracteres definidos no Portable Character Set e não começam com um dígito . Outros caracteres podem ser permitidos por uma implementação; os pedidos devem tolerar a presença de tais nomes.

Portanto, embora os nomes possam ser válidos, seu shell pode não suportar nada além de letras, números e sublinhados.

Robert Gamble
fonte
8
Apenas verificando: a segunda cotação não é normativa: ela apenas observa que as variáveis ​​que o POSIX define como especiais para seus utilitários são [a-zA-Z_][a-zA-Z0-9_]*(sugerindo implicitamente que este formulário é mais saudável), mas a especificação real (cotação 1) requer toda a implementação para oferecer suporte a qualquer coisa, exceto =e NUL?
Ciro Santilli escreveu
3
Além disso, o "conjunto de caracteres portáteis" pubs.opengroup.org/onlinepubs/000095399/basedefs/… contém itens como espaços e não-imprimíveis: então podemos usar essas coisas ou não?
Ciro Santilli escreveu
3
É exatamente isso que observo. O Shell não gosta de caracteres especiais como parte de um nome de variável. No entanto, quando um programa ou script (por exemplo, java ou perl) inicializa uma variável com caracteres especiais em seu nome e chama outro executável (um processo filho), o último executável pode acessar essa variável sem problemas.
oᴉɹǝɥɔ
1
@checksum, UPPERCASE é especificado explicitamente para nomes de variáveis ​​com significado para as ferramentas especificadas no POSIX, incluindo o shell; nomes com pelo menos um caractere minúsculo são explicitamente reservados para uso do aplicativo. Portanto, a melhor prática é incluir pelo menos um caractere minúsculo nos nomes de variáveis ​​de seus aplicativos para garantir que você não substitua acidentalmente (como definir uma variável shell substituirá qualquer variável de ambiente com nome semelhante) uma variável com significado para o sistema. Veja pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy
2
@CiroSantilli 事件 事件 2016 六四 事件 法轮功, você pode usá-los em variáveis ​​de ambiente; você não pode usá-los em variáveis ​​do shell, e não é garantido que essas variáveis ​​de ambiente estejam acessíveis no shell.
Charles Duffy
37

A seção de padrões POSIX em conchas do padrão IEEE 1003.1-2008 / IEEE POSIX P1003.2 / ISO 9945.2 Shell e Ferramentas não define a convenção lexical para nomes de variáveis, no entanto, uma análise superficial da fonte revela que ele usa algo semelhante a

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

(Editar: adicionado sublinhado ausente na 2ª classe de caracteres.)

Uma observação rápida, como alguns shells não suportam o + na regex, uma regex potencialmente mais portátil pode ser:

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

Aiden Bell
fonte
4
Obrigado, Aiden. Eu acho que falta um sublinhado no segundo conjunto de colchetes: Provavelmente deve ser: [a-zA-Z_][a-zA-Z0-9_]* Para aqueles como eu que acham a referência ao bash-4.1 um pouco vaga (616.000 linhas de código), aqui estão algumas dicas para encontre as linhas de código relevantes: subst.c: param_expand(), in the default case-> general.h:/ * Defina exatamente o que consiste um identificador de shell legal. * / #define legal_variable_starter (c) (ISALPHA (c) || ​​(c == ' ')) #define legal_variable_char (c) (ISALNUM (c) || ​​c == ' ')
Chris
3
Você não precisa disso mais na primeira classe de caracteres.
Scravy
2
@scravy verdade, embora eu levei o regexp a partir da fonte, então eu vou manter a + no.
Aiden Sino
4
O POSIX define: 3.231 Nome a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit .
Não na seção shell, mas existem absolutamente os padrões POSIX que incluem convenções para nomeação de variáveis ​​de ambiente (e discutem nomes reservados para uso do shell). Veja pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy
12

Meu teste rápido mostrou que eles basicamente seguem as mesmas regras que os nomes de variáveis ​​C, a saber

  1. az, AZ, _ e 0-9
  2. NÃO pode começar com um número

Portanto, isso exclui .dentro deles. Qualquer nome de variável ilegal é creditado unknown command.

Isso foi testado no ZSH, que é principalmente compatível com BASH.

LukeN
fonte
6

Depende do que você quer dizer com 'permitido'.

Ignorando o Windows para o nonce:

O ambiente é uma matriz de seqüências de caracteres, passadas para a função principal de um programa. Se você ler execve (2), não verá requisitos ou limites nessas cadeias além da terminação nula.

Por convenção, cada sequência consiste em NAME = value. Não há convenção de cotação, portanto você não pode ter um '=' no nome desta convenção.

Humanos normais definem essas cordas discutindo-as com sua concha. Cada shell tem suas próprias idéias sobre quais são os NAMEs variáveis ​​válidos; portanto, você deve ler a página do manual no momento para ver o que pensa.

Geralmente, coisas como com.baseball.spit = fleagh são propriedades do sistema Java e, se algum programa Java deseja ou não retornar ao ambiente, é melhor especificá-los com -D.

bmargulies
fonte
Deveria ter chegado à conclusão de que a variável está formatada como uma propriedade do sistema Java, em vez de tentar defini-la como uma variável de ambiente.
Christian Semrau
4

SIM, VOCÊ PODE FAZER.

Use execeenv comando para implementar esta cena.

Dispositivo de teste no Docker

docker run -it --rm alpine:3.10

Executar comando no contêiner:

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

Verifique as variáveis ​​de ambiente:

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 auxpara verificar se o PID não foi alterado

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

Use pythonpara verificar a variável environmentemnt

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

OUTPUT é happy-variable-name .

O que acontece?

  1. Execução de chamada interna do shell
  2. O comando exec incorporado ao shell syscall.exec cria o processo 'env' para substituir o shell atual
  3. processo env chame syscall.execvp create process '/ bin / sh' para substituir o processo env

Outra maneira

  • Imagem do Docker

Se você estiver usando a janela de encaixe, poderá definir variáveis ​​no Dockerfile

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

Se você estiver usando o kubernetes, poderá configurar a variável pelo 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

Implantar pod kubectl apply -f test.yaml

Verifique a kubectl logs foobarsaída:

xx.ff-bar=1234

O ConfigMap permite '-', '_' ou '.'

Zealic
fonte
0

Embora a maioria dos shell não permita definir variáveis ​​de ambiente (conforme mencionado em outras respostas), se você precisar, poderá executar outros programas com variáveis ​​de ambiente não padrão usando env(1) .

Por exemplo, apagando todo o ambiente e definindo Strange.Env:Varcomo valor fooe executando o programa perl que o imprime:

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

irá imprimir

$VAR1 = {
          'Strange.Env:Var' => 'foo'
        };
Matija Nalis
fonte