Qual é a diferença entre set, export e env e quando devo usar cada um?

87

De vez em quando eu bato um script e parece que existem algumas maneiras de definir uma variável:

key=value
env key=value
export key=value

Quando você está dentro de um script ou de um único comando (por exemplo, eu geralmente encadeado uma variável com um iniciador do Wine para definir o prefixo Wine correto) eles parecem ser completamente intercambiáveis, mas certamente não pode ser o caso.

Qual é a diferença entre esses três métodos e você pode me dar um exemplo de quando eu gostaria especificamente de usar cada um deles?

Definitivamente relacionado a Qual é a diferença entre 'VAR = ...' e 'export VAR = ...'? mas eu quero saber como env se encaixa nisso também, e alguns exemplos mostrando os benefícios de cada um também seriam bons:)

    
por Oli 24.10.2012 / 11:34

1 resposta

86

Vamos considerar um exemplo específico. O comando grep usa uma variável de ambiente chamada GREP_OPTIONS para definir opções padrão.

Agora. Dado que o arquivo test.txt contém as seguintes linhas:

line one
line two

executando o comando grep one test.txt retornará

line one

Se você executar o grep com a opção -v , ele retornará as linhas não correspondentes, então a saída será

line two

Vamos agora tentar definir a opção com uma variável ambiental.

  1. As variáveis de ambiente definidas sem export não serão herdadas no ambiente dos comandos que você está chamando.

    GREP_OPTIONS='-v'
    grep one test.txt
    

    O resultado:

    line one
    

    Obviamente, a opção -v não foi passada para grep .

    Você deseja usar este formulário quando estiver definindo uma variável somente para o shell a ser usado, por exemplo, em for i in * ; do você não deseja exportar $i .

  2. No entanto, a variável é passada para o ambiente daquela linha de comando em particular, então você pode fazer

    GREP_OPTIONS='-v' grep one test.txt
    

    que retornará o esperado

    line two
    

    Você usa este formulário para alterar temporariamente o ambiente desta instância específica do programa lançado.

  3. Exportar uma variável faz com que a variável seja herdada:

    export GREP_OPTIONS='-v'
    grep one test.txt
    

    retorna agora

    line two
    

    Esta é a forma mais comum de definir variáveis para o uso de processos subsequentemente iniciados em um shell

  4. Tudo isso foi feito no bash. export é um bash embutido; VAR=whatever é a sintaxe bash. env , por outro lado, é um programa em si. Quando env é chamado, as seguintes coisas acontecem:

    1. O comando env é executado como um novo processo
    2. env modifica o ambiente e
    3. chama o comando que foi fornecido como um argumento. O processo env é substituído pelo processo command .

    Exemplo:

    env GREP_OPTIONS='-v' grep one test.txt
    

    Este comando lançará dois novos processos: (i) env e (ii) grep (na verdade, o segundo processo substituirá o primeiro). Do ponto de vista do processo grep , o resultado é exatamente o mesmo que em execução

    GREP_OPTIONS='-v' grep one test.txt
    

    No entanto, você pode usar esse idioma se estiver fora do bash ou não quiser iniciar outro shell (por exemplo, quando estiver usando a família de funções exec() em vez da chamada system() ).

Nota adicional sobre #!/usr/bin/env

É também por isso que o idioma #!/usr/bin/env interpreter é usado em vez de #!/usr/bin/interpreter . env não requer um caminho completo para um programa, porque ele usa a função execvp() que pesquisa a variável PATH da mesma forma que um shell, e então substitui pelo comando run . Assim, ele pode ser usado para descobrir onde um interpretador (como perl ou python) "se senta" no caminho.

Isso também significa que, modificando o caminho atual, você pode influenciar qual variante do python será chamada. Isso possibilita o seguinte:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

em vez de lançar o Caliber, resultará em

I am an evil interpreter!
    
por January 24.10.2012 / 12:21