Não é possível originar com êxito .bashrc a partir de um script de shell

51

Normalmente, podemos obter o ~/.bashrcarquivo de origem usando este comando

source ~/.bashrc

mas se eu escrever isso em um shell script e executá-lo, nada acontece. Por quê?
Há alguma maneira de fazer isso?

Meu script:

#!/bin/bash
chmod a+x ~/.bashrc
source ~/.bashrc

Também tentei .(ponto) em vez de source. Mesmo resultado.

shantanu
fonte

Respostas:

26

Um script de shell é executado em sua própria instância de shell. Todas as configurações de variáveis, definições de funções e outras coisas afetam apenas essa instância (e talvez seus filhos), mas não o shell de chamada; portanto, elas desaparecem após a conclusão do script.

Por outro lado, o sourcecomando não inicia uma nova instância do shell, mas usa o shell atual para que as alterações permaneçam.

Se você quiser que um atalho leia seu .bashrc, use uma função shell ou um alias em vez de um script shell, como

alias brc='source ~/.bashrc'
Florian Diesch
fonte
Obrigado pela sua resposta rápida. Sua solução talvez funcione, mas eu tenho que editar o arquivo bashrc manualmente para salvar a linha 'aliac brc = ....'. Estou tentando desenvolver uma interface gráfica para alterar a variável de ambiente. Portanto, não posso editar o arquivo bashrc de outro computador manualmente.
Shantanu
11
Você deve executar source ~/.bashrcno shell do qual deseja alterar o ambiente. Você não pode alterá-lo de outro processo. Talvez (globalmente) a adição desse alias possa fazer parte do processo de instalação da sua GUI.
Florian Diesch 5/10
11
Então, eu coloquei seu comando de alias anteriormente no script e invoquei o brc quando quiser obter meu .bashrc ou preciso colocar esse comando de alias em um arquivo em algum lugar?
user137717
O que acabei fazendo é uma extensão da resposta de Florian Diesch. Você pode apenas usar um alias de várias linhas: alias brc = 'chmod a + x ~ / .bashrc; source ~ / .bashrc 'Eu ainda sou bastante novo, então não tenho certeza se isso é considerado' má prática '. Mas funciona.
A_user_appears
13

Você .bashrcgeralmente começa:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Como seu script não possui o PS1 definido (porque não é interativo), ele não redefine o caminho porque sai mais cedo. Para demonstrar, modifique seu script:

    #!/bin/bash
    chmod a+x ~/.bashrc
    PS1='$ '
    source ~/.bashrc

Agora, isso permitirá que seus scripts funcionem com o novo .bashrc. Nota: assim que o script sair, o ambiente será definido como era antes de iniciar o script. As alterações serão refletidas na próxima vez que um terminal for iniciado.

ravi nankani
fonte
Pelo menos desde 16.04 e provavelmente antes, o Ubuntu padrão .bashrcusa uma maneira mais confiável de verificar se o shell é interativo. /etc/bash.bashrcainda tem o teste PS1.
Zanna
12

Experimentar:

exec bash

Isso deve recarregar ~ / .bashrc, ~ / .bash_aliases, etc.

Alin Andrei
fonte
9
Isso substitui o processo atual do bash por um novo. Não é muito mais curto ou mais fácil do que usar, sourcemas destrói todas as variáveis ​​que o usuário definiu manualmente - o que pode ou não o que você deseja.
Florian Diesch 5/10
espere, no contexto de um script do Shell com outros comandos após a fonte bashrc, você coloca os comandos que precisam do novo estado bash depois disso exec bash, da maneira que eu entendo o comando depois ainda estará nas mesmas configurações do bash de antes?
tatsu 4/03
11

Quero complementar a resposta de ravi :

Esse comportamento é específico ao Ubuntu (e provavelmente à maioria das distribuições derivadas), pois o ~/.bashrcarquivo padrão inicia com um curto-circuito, o Ubuntu 18.04, por exemplo:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Isso interromperá a avaliação do arquivo se ele estiver em execução em um shell não interativo, que é o caso do seu script, pois todos os scripts são executados em um shell não interativo e, subsequentemente, em todos os arquivos que você sourceherdará essa propriedade.

eval hackear

Eu descobri um truque feio para solucionar o Ubuntu especificamente, usando em evalvez de source:

eval "$(cat ~/.bashrc | tail -n +10)"

Ele simplesmente pula as poucas primeiras linhas e avalia o restante, ~/.bashrcpara que o restante seja avaliado e modifique a execução atual.

Esteja ciente de que é um número mágico e pode não funcionar nas versões do Ubuntu; mas pode ser uma boa solução se você estiver criando scripts para sistemas mais ou menos conhecidos.

Uma solução mais sofisticada pode envolver o uso de regex para direcionar os bits específicos que interrompem a avaliação.

Alternativa de Shebang

Outra alternativa que pode funcionar melhor em alguns cenários é forçar a execução do script em um shell interativo adicionando um sinalizador no shebang :

#!/bin/bash -i

Esteja ciente de algumas coisas:

stefanmaric
fonte
2

Nenhum dos outros métodos funcionou para mim [ source /path/to/filevs . ./path/to/file, alias, etc ...], até que, graças a este tutorial , descobri que usando o:

#!/usr/bin/env bash shebang

em vez do mais simples, #!/usr/bin/envpermite que os argumentos sejam transmitidos ao intérprete, que eu acho que é a chave aqui - consulte este documento para obter mais informações.

De qualquer forma, se os comandos de origem de qualquer forma não estiverem funcionando para você, tente verificar seu shebang, esse pode ser o problema :)

Nikksno
fonte