Exportar uma variável env para estar disponível em todas as sub-cascas, e possível de ser modificada?

21

Suponha que eu tenha

export MY_VAR=0

em ~/.bashrc .

Eu tenho um terminal gnome aberto e, neste terminal, altero o valor $MY_VAR para 200 . Então, se eu fizer

echo $MY_VAR

neste terminal, 200 é mostrado.

Agora, abri outra guia no meu terminal do gnome e faço

echo $MY_VAR

... e, em vez de 200 , tenho 0 .

O que devo fazer para persistir o valor 200 quando um terminal modifica uma variável de ambiente, disponibilizando essa modificação (configuração para 200) para todas as sub-cascas subseqüentes e tal? Isso é possível?

    
por Somebody still uses you MS-DOS 28.02.2011 / 19:31

5 respostas

23

Uma cópia do ambiente é propagada para sub-shells, então isso funciona:

$ export MY_VAR=200
$ bash
$ echo $MY_VAR
200

mas como é uma cópia, você não pode obter esse valor para o shell pai - não alterando o ambiente, pelo menos.

Parece que você realmente quer dar um passo adiante, que é fazer algo que aja como uma variável global, compartilhada por shells "irmãos" iniciados separadamente do pai - como sua nova aba no Terminal do Gnome.

Principalmente, a resposta é "você não pode, porque as variáveis de ambiente não funcionam dessa maneira". No entanto, há outra resposta, que é, bem, você pode sempre hackear alguma coisa. Uma abordagem seria escrever o valor da variável em um arquivo, como ~/.myvar , e incluir isso em ~/.bashrc . Em seguida, cada novo shell será iniciado com o valor lido desse arquivo.

Você poderia ir além - faça ~/.myvar estar no formato MYVAR=200 e, em seguida, defina PROMPT_COMMAND=source ~/.myvar , o que faria com que o valor fosse relido toda vez que você obtivesse um novo prompt. Ainda não é bastante uma variável global compartilhada, mas está começando a agir como tal. Ele não será ativado até que um aviso retorne, o que, dependendo do que você está tentando fazer, pode ser uma séria limitação.

E então, é claro, a próxima coisa é automaticamente escrever alterações em ~/.myvar . Isso fica um pouco mais complicado, e eu vou parar neste ponto, porque, na verdade, as variáveis de ambiente não foram feitas para ser um mecanismo de comunicação entre shell, e é melhor apenas encontrar outra maneira de fazê-lo.

    
por 28.02.2011 / 19:53
13

Suppose I have export MY_VAR=0 in ~/.bashrc.

Esse é o seu erro aí mesmo. Você deve definir suas variáveis de ambiente em ~/.profile , que é lido quando você efetua login. ~/.bashrc é lido toda vez que você inicia um shell; quando você inicia o shell interno, ele substitui MY_VAR . Se você não tivesse feito isso, sua variável de ambiente se propagaria para baixo.

Para obter mais informações sobre ~/.bashrc vs ~/.profile , consulte meu anterior mensagens < href="https://superuser.com/questions/187639/zsh-not-hitting-profile"> em este tópico .

Note que a propagação ascendente (recebendo um valor modificado da subshell automaticamente refletido no shell pai) não é possível, ponto final.

    
por 28.02.2011 / 22:42
4

O shell de peixe pode fazer isso com:

set -U MY_VAR 0

(consulte link )

Para executar um comando fish a partir de outro shell, você pode executar fish -c , por ex. :

fish -c "set -u MY_VAR 0"
    
por 11.12.2014 / 14:28
3

Não use variáveis de ambiente. Use arquivos.

Para impedir que os processos avancem uns aos outros ao atualizar / ler o arquivo, use arquivos de bloqueio e pequenos scripts de atualização de front-end cuja finalidade é apenas atualizar um arquivo com $ 1 se ele não estiver bloqueado. Lockfiles são implementados, basicamente, verificando se existe um arquivo específico (/var/run/yourscript.lck) e, se isso acontecer, espere o arquivo desaparecer por um tempo e falhe se não. Além disso, você deve excluir o arquivo de bloqueio quando terminar de atualizar o arquivo.

Esteja preparado para lidar com uma situação em que um script não pode atualizar um arquivo porque o arquivo está ocupado.

    
por 28.02.2011 / 20:40
1

Quando acabei de pesquisar essa questão, tentei resolver o problema de atualização de estado (ou seja, variáveis de shell) de sub-shell. Assim, alguém poderia atribuir variáveis, digamos, dentro de um pipeline - e a atribuição seria visível de maneira transparente para o pai.

Claro, isso não é possível de forma simples, porque partes individuais de um pipeline são executadas em subshells, que são fork 'ed do shell pai e, portanto, têm memória que é copy-on-write veja a memória dos pais. No entanto, eu supus que uma solução leve e transparente poderia ser possível com base em " memória compartilhada " tipo IPCs .

E até encontrei uma implementação exatamente desse design ... mas é em Perl.

Adicionando esta resposta de qualquer forma como uma possível solução.

    
por 06.03.2012 / 13:24