AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 792546
Accepted
Arch Stanton
Arch Stanton
Asked: 2025-03-16 18:52:43 +0800 CST2025-03-16 18:52:43 +0800 CST 2025-03-16 18:52:43 +0800 CST

O que os programas usam para ler seu ambiente?

  • 772

Estou no Fedora, onde todos os shells pré-instalados aparentemente suportam bashisms: bash --posixdoes, e até mesmo sh. Ainda assim, quando usei esta função ,

pathprepend () {
    if [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="$1${PATH:+":$PATH"}"
    fi
}

para adicionar um diretório a PATHpartir de ~/.profile, o Git não o pegou. Note que echo $PATHna sessão bash da qual eu estava usando o Git listou meu diretório, notei que só porque eu uso diff-highlight, symlinked naquele diretório, e depois que comecei a usar a pathprependfunção acima o Git reclamou que diff-highlightestava faltando. Depois de restaurar uma PATHconfiguração compatível com POSIX, ele voltou a funcionar normalmente.

Isso me deixou pensando o que os programas usam para ler seu ambiente. Cada um deles vem com seu próprio mecanismo para fazer isso? Eles deixam o trabalho para algum shell ou biblioteca do sistema?


Editar

@Bodo, é isso que eu costumava fazer: em ~/.profile,

pathprepend () {
    if [[ ":$PATH:" != *":$1:"* ]]; then
        PATH="$1${PATH:+":$PATH"}"
    fi
}

pathprepend "$HOME/.local/bin"

Por "compatível com POSIX" quero dizer sem nenhuma bashism. Isto é o que tenho agora em ~/.profile:

pathprepend () {
  case ":$PATH:" in
    *":$1:"*)
      :;;
    *)
      PATH="$1${PATH:+":$PATH"}";;
  esac
}

pathprepend "$HOME/.local/bin"

Em ambos os casos ~/.profileé proveniente de ~/.bash_profile, que contém

# Load the configuration for login sessions of any shell
if [[ -f "$HOME/.profile" ]]; then
  source "$HOME/.profile"
else
  echo >&2 "$HOME/.bash_profile: $HOME/.profile not found"
fi

# Load the configuration for interactive non-login Bash sessions
case "$-" in *i*)
  if [[ -f "$HOME/.bashrc" ]]; then
    source "$HOME/.bashrc"
  else
    echo >&2 "$HOME/.bash_profile: $HOME/.bashrc not found"
  fi;;
esac

Não fiz isso export PATHporque Gordon Davisson explica na resposta da qual copiei a função que " PATHjá deveria estar marcado como exportado, então não é necessário reexportar". Na verdade, ainda não fiz, exportmas com a caseversão de pathprependtudo funciona bem. A propósito, qual é o processo pai do processo Git, é o processo Bash do qual eu uso git?

shell-script
  • 1 1 respostas
  • 878 Views

1 respostas

  • Voted
  1. Best Answer
    Stéphane Chazelas
    2025-03-16T23:20:14+08:002025-03-16T23:20:14+08:00

    os programas obtêm seu ambiente do terceiro argumento da execve(program_path, argv, envp)chamada de sistema que os executou.

    envp, como argvé uma matriz de strings, exceto que envp, por convenção, as strings estão no var=valueformato .

    O que os programas fazem com essas strings depende deles, mas geralmente eles pegam essas var=valuestrings e interpretam o que está à esquerda da primeira =como o nome de uma variável de ambiente e o que está à direita como seu valor.

    Eles geralmente armazenam essa lista de lado e quando eles, no mesmo processo ou em um processo filho, executam outros comandos, eles passam essa mesma lista no terceiro argumento para a execve()chamada de sistema correspondente.

    A biblioteca C tem ajudantes para isso. Essa lista armazenada à parte é a environvariável ali, e as funções putenv()/ setenv()/ unsetenv()podem ser usadas para adicionar/modificar/remover variáveis ​​ali e funções como execlp()são wrappers para a execve()chamada do sistema que passam isso environadiante automaticamente como envp. A ideia é que o ambiente seja algo que seja herdado automaticamente durante a execução¹.

    A maioria dos shells mapeia variáveis ​​de ambiente para variáveis ​​de shell.

    Em shells do tipo POSIX, variáveis ​​que envptêm um nome compatível com o de uma variável de shell são convertidas em uma variável de shell que é marcada com o exportatributo . E o exportutilitário especial embutido pode ser usado para promover uma variável de shell para uma variável de ambiente para que ela seja passada em envpcada comando executado depois disso.

    ~/.profileé um arquivo de inicialização de sessão que é interpretado pela maioria dos shells do tipo Bourne quando são invocados como shells de login (o que loginé feito adicionando um -a argv[0]). O equivalente para shells do tipo csh seria ~/.login, veja também ~/.zprofile/ ~/.zloginpara zsh.

    Hoje em dia, isso normalmente é lido ao efetuar login ssh( ssh hostsomente no rloginmodo , não ssh host 'shell code'no rshmodo que não efetua login) ou em um terminal virtual ou sudo -i, raramente por emuladores de terminal iniciados dentro de uma sessão de login gráfico.

    Alguns ambientes gráficos tentam iniciar o shell de login do usuário como invocações de shell de login não interativas que interpretam esses arquivos de ambiente de sessão no login em uma tentativa de obter as mesmas variáveis ​​de ambiente lá, mas não todas. Outros mecanismos são às vezes usados ​​lá para definir variáveis ​​de ambiente.

    Se, ao efetuar login, seu shell de login foi iniciado como um shell de login e é do tipo Bourne (e não zsh), ele terá interpretado o código em ~/.profile.

    Ao interpretar, PATH="~/.local/bin${PATH:+":$PATH"}"ele terá atualizado a variável $PATH do shell . Como essa variável terá sido encontrada no envpque foi passado para esse shell, essa variável será marcada para exporte a variável com seu valor modificado² será incluída no envppassado para cada comando executado depois disso, incluindo git. Se gitfizer um getenv("PATH"), ele deve obter esse valor modificado.

    Mas para que isso aconteça, o ~/.profiledeve ter sido interpretado por um shell na ancestralidade do processo que o executou git.


    ¹ Não deve ser confundido com o relacionamento pai/filho. Um filho herda tudo de seu pai, mas a execução apaga toda a memória e é onde você precisa de um mecanismo como o ambiente para passar informações.

    ² Exceto no Bourne shell, onde a modificação da variável do shell não é refletida na variável de ambiente, a menos que você chame export. Mas você não encontrará o Bourne shell no Fedora nem em nenhum sistema moderno.

    • 7

relate perguntas

  • Subtraindo a mesma coluna entre duas linhas no awk

  • Um script que imprime as linhas de um arquivo com seu comprimento [fechado]

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Dividir por delimitador e concatenar problema de string

  • MySQL Select com função IN () com array bash

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve