Adicione diretórios ao $ PATH sem se repetir

5

Meu shell é zsh e o SO é Ubuntu 13.04

Eu preciso adicionar o diretório ao $ PATH para que ele funcione nos seguintes locais:

  • No ambiente gráfico (Unity) (como aplicativos de inicialização, gmrun programa executado por atalho (basicamente como "Executar comando" em alt + f2)
  • No terminal na Unity
  • No terminal em Ctrl + Alt + F1

Eu adicionei em .profile e ele funciona nos dois primeiros pontos, mas não no último. Eu sei que eu posso adicioná-lo a .zshrc mas neste caso ele será escrito em locais de reboque (viola DRY) e no caso de terminal dentro de unidade será duas vezes em $PATH (eu não acho que é muito ruim, mas pelo menos não é bonito)

Se eu adicioná-lo apenas a .zshrc , ele funciona apenas para segundo e terceiro casos (obviamente)

O que posso fazer?

    
por RiaD 30.07.2013 / 18:07

3 respostas

1

Esta resposta é basicamente baseada na de Eliah Kagan e contém o que eu realmente fiz.

Adicionei a ~/.pam_environment

PATH DEFAULT=${PATH}:/home/riad/scripts

Mas pelo menos no meu PC ele não foi analisado no login tty1 ( Ctrl + Alt + F1 ) mas foi analisado no login gráfico . (Mesmo as configurações de localidade criadas pela unidade não funcionavam no login não gráfico)

O motivo é que havia a seguinte linha no arquivo de configuração pam para lightdm ( /etc/pam.d/lightdm ):

session required        pam_env.so readenv=1 user_readenv=1 envfile=/etc/default/locale

Adicionei a mesma linha a /etc/pam.d/login entre

@include common-session

e

@include common-password

Tenha cuidado! Um arquivo .pam_environment ruim pode ter quebrado seu login.

    
por RiaD 01.08.2013 / 06:18
4

Definindo uma variável de ambiente para todos os logins (independentemente do tipo)

A melhor maneira é usar ~/.pam_environment . Por exemplo, para adicionar /opt/blah/bin ao final de sua PATH , você colocaria isso no arquivo .pam_environment no seu diretório pessoal:

PATH DEFAULT=${PATH}:/opt/blah/bin

Definindo Variáveis de Ambiente Globalmente (mas não faça isso a menos que seja necessário)

Se você quiser adicionar algo ao PATH para todos os usuários , use /etc/environment . Confusamente, /etc/environment e ~/.pam_environment não usam a mesma sintaxe. Embora nenhum deles seja realmente um script, /etc/environment parece um script ( sem nenhum comando export ). Então, se você quiser adicionar /opt/blah/bin ao final de todo mundo PATH , e a PATH linha em /etc/environment começou como

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"

você mudaria para:

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/blah/bin"

Análise

A maioria dos shells no estilo Bourne, incluindo bash , irá fornecer ~/.profile quando eles forem iniciados como um shell de login. zsh é uma exceção incomum; ele só fará isso se for invocado com o nome de uma das shells tradicionais ao estilo Bourne. Ou seja, se você chamar zsh pelo nome sh ou ksh (mais comumente obtido criando um link simbólico para zsh com um desses nomes), ele se comportará como eles e fonte ~/.profile (se for um shell de login). Caso contrário, não será. (Fonte: man zsh .)

É por isso que zsh em uma sessão console virtual (por exemplo, onde você vai para Ctrl + Alt + F1 ) não define a variável de ambiente PATH de ~/.profile . É um shell de login, mas zsh é especial; ela não se comporta como conchas tradicionais ao estilo Bourne, a menos que esteja fingindo ser uma.

Por que zsh executando uma janela do Terminal tem as variáveis de ambiente definidas em ~/.profile ? Porque eles já estavam configurados na sua sessão gráfica antes de você iniciar o Terminal . Quando você faz login graficamente, o gerenciador de exibição (que fornece a tela de login gráfica e gerencia as sessões gráficas) age como um shell de login. Geralmente, ele obtém ~/.profile (embora não seja garantido que o faça, e ocasionalmente alguém altera os ambientes de área de trabalho apenas para descobrir que ~/.profile não é mais fornecido quando eles fazem login graficamente). / p>

Não há nada sobre consoles virtuais baseados em texto que faz com que ~/.profile não seja originado. Por exemplo, se seu shell fosse bash em vez de zsh e você estivesse conectado em um console virtual, ~/.profile seria originado. A questão é que, ao contrário do comportamento confiável de um shell tradicional estilo Bourne, e o comportamento não tão confiável de um gerenciador de exibição ao iniciar uma sessão de login gráfica, zsh não origina ~/.profile quando for seu shell de login. / p>

Da mesma forma, com as variáveis de ambiente definidas em ~/.profile , se você fizesse login remotamente (por exemplo, ativando o SSH e registrando dessa maneira), ~/.profile não seria originado.

Isso se aplica também ao arquivo global /etc/profile , por sinal. Se você definir variáveis de ambiente globalmente, você perceberá o mesmo comportamento que está vendo as variáveis de ambiente de configuração para seu usuário em ~/.profile .

A solução, desde que você não precise escrever um teste com script para determinar o conteúdo de suas variáveis de ambiente , é definir variáveis de ambiente específicas do usuário em ~/.pam_environment e em todo o sistema , para todos os usuários) variáveis de ambiente em /etc/environment .

Quando você faz isso, PAM (especificamente, pam_env.so ) define as variáveis no login, basicamente para cada tipo de login, e faz isso antes o shell de login (por exemplo, zsh , bash para a maioria das pessoas) ou coisa semelhante a um shell de login (por exemplo, um gerenciador de exibição) origina seus próprios arquivos de configuração de login. Esta é a maneira geralmente recomendada de definir variáveis de ambiente no Ubuntu atualmente .

Desta forma, resolve-se o problema de algumas shells de login que nem sempre obtêm ~/.profile e /etc/profile (que é o problema que você está enfrentando). Ele também resolve o problema ocasional de um gerenciador de exibição não fornecer esse arquivo à medida que ele inicializa uma sessão de login gráfica (esse é um problema que você não está experimentando).

Alternativas

E se:

  • você precisa definir variáveis de ambiente no login, com base nos resultados de testes com script? Ou
  • você não quer usar .pam_environment (ou para variáveis de todo o sistema, /etc/environment ?

Se você não estava usando zsh , mas em vez disso usou bash ou outro shell estilo tradicional mais Bourne, você poderia definir suas variáveis de ambiente em ~/.profile (ou /etc/profile para variáveis do sistema). Ocasionalmente, há uma configuração em que isso não é configurado para sessões de login gráficas, mas geralmente funciona.

Defini-las em ~/.bashrc não funcionará para este fim . Essencialmente apenas bash sources que arquiva, então ele não funcionará nem quando zsh é seu shell de login nem quando o gerenciador de exibição age como seu shell de login. (Em outras palavras, na sua situação, isso nunca funcionará).

Assim, se você precisar de um script originado para todos os tipos de login, e ~/.profile estiver sendo originado para suas sessões gráficas, você pode simplesmente:

  • modificar a configuração de zsh para a origem ~/.profile , ou
  • faça a configuração de zsh e ~/.profile forneça um terceiro arquivo compartilhado. (Isso pode até ser adicionado a um arquivo de configuração separado para sessões gráficas, como .xsession , se isso para ser necessário mais tarde.)

Dessas duas opções, a segunda é melhor, a menos que você tenha lido o conteúdo de ~ / .profile and made sure they--and the contents of any script sourced from .profile --won't cause problems if sourced by zsh '. (Geralmente não deveria, mas você nunca sabe.)

O melhor arquivo de configuração a ser modificado, para tornar zsh source ~/.profile (ou algum outro script) no login, é ~/.zprofile . Isso corresponde a ~/.profile em shells mais tradicionais ao estilo Bourne. (Estritamente falando, é $ZDOTDIR/.zprofile , mas $ZDOTDIR é normalmente ~ .)

Você adicionaria a linha source $HOME/.profile a esse arquivo.

Eu enfatizo, no entanto, que se precisar executar uma atribuição simples para variáveis de ambiente (incluindo atribuição recursiva onde uma variável de ambiente é atribuída a uma expressão contendo ela mesma e / ou outras variáveis de ambiente), você deve usar ~/.pam_environment como explicado acima (ou /etc/environment para variáveis de ambiente em todo o sistema).

    
por Eliah Kagan 30.07.2013 / 19:02
1

Primeiro de tudo, você poderia apenas fornecer seu .profile em seu arquivo .zshrc.

Além disso, enquanto estiver usando o zsh, você pode adicionar o seguinte ao seu .zshrc:

typeset -U path

# If you want it at the front of your path
path=({/custom/path/bin "${path[@]}")

# If you want it at the end of your path
path+=(/custom/path/bin)

Como isso funciona:

No zsh, a variável $PATH está vinculada à variável $path ; $path é uma matriz e $PATH é um escalar com os elementos $path unidos por : (idêntico a ${(j|:|)path} ). typeset -U path torna os elementos da matriz path (e, portanto, $PATH ) exclusivos.

   typeset [ {+|-}AEFHUafghklprtuxmz ] [ -LRZi [ n ]] [ name[=value] ... ]
   typeset -T [ {+|-}Urux ] [ -LRZ [ n ]] SCALAR[=value] array [ sep ]
          Set or display attributes and values for shell parameters.
          (...)
          -U     For  arrays  (but  not for associative arrays), keep only
                 the first occurrence of each duplicated value.  This  may
                 also  be  set for colon-separated special parameters like
                 PATH or FIGNORE, etc.  This flag has a different  meaning
                 when used with -f; see below.
    
por Kevin 30.07.2013 / 18:56