A que propósito serve o [ -n "$PS1" ]
in [ -n "$PS1" ] && source ~/.bash_profile;
? Esta linha está incluído em um .bashrc
de um dotfiles repo .
10
Isso está verificando se o shell é interativo ou não. Nesse caso, apenas procure o ~/.bash_profile
arquivo se o shell for interativo.
Consulte "Este shell é interativo?" no manual do bash, que cita esse idioma específico. (Também recomenda verificar se o shell é interativo, testando se a $-
variável especial contém o i
caractere, o que é uma abordagem melhor para esse problema.)
( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )
, o que simplesmente imprime[]
. Parece que o zsh não faz o mesmo, pelo menos a partir de um experimento ... De qualquer forma, a intenção do[ -n "$PS1" ]
é verificar se o shell é interativo ou não.bash
desativa o PS1 quando não interativo (erro de digitação no seu comentário anterior) é um bug da IMO, o PS1 não é uma variável específica do bash, não há negócios em desabilitá-lo. É o único shell que faz isso (emborayash
também seja definidoPS1
como um valor padrão mesmo quando não interativo).[[ $- = *i* ]] && source ~/.bash_profile
).[ -n "${PS1}" ]
, mas ainda atualizei minha resposta para destacar que o manual do bash também sugere / recomenda a inspeção$-
para determinar se o shell é interativo, espero que você ache que melhora a resposta. Felicidades!O que isso faz
Essa é uma maneira generalizada de testar se o shell é interativo. Cuidado que ele só funciona no bash, não funciona com outras conchas. Portanto, está tudo bem (se for bobo)
.bashrc
, mas não funcionaria.profile
(o que é lido por sh, e o bash é apenas uma das implementações possíveis do sh, e não a mais comum).Por que funciona (apenas no bash!)
Um shell interativo define a variável
PS1
do shell como a sequência de prompt padrão. Portanto, se o shell é interativo,PS1
está definido (a menos que o usuário o.bashrc
tenha removido, o que ainda não pode ter acontecido no topo.bashrc
, e você pode considerar que é uma coisa boba de se fazer).O inverso é verdadeiro no bash: instâncias não interativas do bash desativadas
PS1
quando iniciadas. Observe que esse comportamento é específico do bash e é sem dúvida um bug (por quebash -c '… do stuff with $var…'
não funcionaria quandovar
éPS1
?). Mas todas as versões do bash até o 4.4 (inclusive a versão mais recente que eu escrevo) fazem isso.Muitos sistemas exportam
PS1
para o meio ambiente. É uma má idéia, porque muitos shells diferentes usam,PS1
mas com uma sintaxe diferente (por exemplo , escapes de prompt do bash são completamente diferentes dos escapes de prompt do zsh ). Mas é bastante difundido que, na prática, ver o quePS1
está definido não é um indicador confiável de que o shell seja interativo. O shell pode ter herdadoPS1
do ambiente.Por que é (mis) usado aqui
.bashrc
é o arquivo que o bash lê na inicialização quando é interativo. Um fato menos conhecido é que o bash também lê.bashrc
um shell de logon e as heurísticas do bash concluem que esta é uma sessão remota (o bash verifica se seu pai érshd
ousshd
). Nesse segundo caso, é improvável quePS1
isso seja definido no ambiente, porque nenhum arquivo de ponto foi executado ainda.No entanto, a maneira como o código usa essas informações é contraproducente.
.bash_profile
nesse shell. Mas.bash_profile
é um script de tempo de login. Pode executar alguns programas que devem ser executados apenas uma vez por sessão. Pode substituir algumas variáveis de ambiente que o usuário definiu deliberadamente para um valor diferente antes de executar esse shell. A execução.bash_profile
em um shell sem logon é perturbadora..bash_profile
. Mas este é o caso em que o carregamento.bash_profile
pode ser útil, porque um shell de login não interativo não carrega/etc/profile
e automaticamente~/.profile
.Eu acho que a razão pela qual as pessoas fazem isso é para usuários que efetuam login através de uma GUI (um caso muito comum) e que colocam suas configurações de variáveis de ambiente em
.bash_profile
vez de.profile
. A maioria dos mecanismos de login da GUI é chamada,.profile
mas não.bash_profile
(a leitura.bash_profile
exigiria a execução do bash como parte da inicialização da sessão, em vez de sh). Com essa configuração, quando o usuário abre um terminal, ele obtém suas variáveis de ambiente. No entanto, o usuário não obterá suas variáveis de ambiente nos aplicativos GUI, o que é uma fonte muito comum de confusão. A solução aqui é usar em.profile
vez de.bash_profile
definir variáveis de ambiente. Adicionar uma ponte entre.bashrc
e.bash_profile
cria mais problemas do que resolve.O que fazer em vez disso
Existe uma maneira simples e portátil de testar se o shell atual é interativo: teste se a opção
-i
está ativada.Isso é útil
.bashrc
para ler.profile
apenas se o shell não for interativo - ou seja, o oposto do que o código faz! Leia.profile
se o bash é um shell de logon (não interativo) e não o leia se for um shell interativo.fonte
[[ -o interactive ]]
(ksh, bash, zsh) oucase $- in (*i*) ...; esac
(POSIX)PS1
se não for executado de forma interativa. É fácil testar:PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
não imprime nada, enquantoPS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
imprime o valor$PS1
definido nos arquivos de inicialização do bash (não imprime a string "cuckoo").$-
contenhai
um shell interativo.[ -n "${PS1}" ]
errado está indo um pouco longe demais, afinal só quebra quando alguém está exportando o PS1 (que na sua resposta você diz que é uma péssima idéia e até explica as razões) e isso não afeta bash de qualquer maneira (já que desabilita o PS1 e o PS2 se o shell não for interativo.) Talvez usar uma palavra como "desanimado" ou falar sobre as "limitações" da abordagem fosse melhor. Eu não acho que esteja "errado" por completo. Se algo estiver errado na exportação do PS1, com certeza! De qualquer forma, obrigado por entrar em detalhes.Parece que esse conceito estranho é resultado do fato de
bash
não ter começado como um clone do shell POSIX, mas como umBourne Shell
clone.Como resultado, o comportamento interativo do POSIX (
$ENV
chamado de shells interativos) foi adicionado posteriormentebash
e não é amplamente conhecido.Há um shell que concede comportamento semelhante. São
csh
concessões e csh que$prompt
possuem valores específicos:Mas isso não se aplica ao shell Bourne nem aos shells POSIX.
Para um shell POSIX, o único método concedido é colocar código para shells interativos no arquivo:
que tem um nome específico do shell. É por exemplo
Outras pessoas mencionaram o sinalizador de shell
-i
, mas isso não é utilizável para programação confiável. O POSIX não exige queset -i
funcione nem que$-
contenha umi
para shells interativos. O POSIX exige apenas que imponhash -i
o shell ao modo interativo.Como a variável
$PS1
pode ser importada do ambiente, ela pode ter um valor mesmo no modo não interativo. O fato de quebash
unset
sPS1
em qualquer shell não interativo não é concedido pelo padrão e não é feito por qualquer outro shell.Portanto, a programação limpa (mesmo com
bash
) é colocar os comandos para shells interativos$HOME/.bashrc
.fonte
Vou falar primeiro sobre o que o Debian, e na maioria das vezes também o Ubuntu define para o bash. E último toque em outros sistemas.
Na configuração dos arquivos de início do shell, há muita opinião.
Eu também tenho minha opinião, mas tentarei mostrar exemplos existentes de configurações corretas.
Vou usar o debuan, pois é muito fácil encontrar exemplos de seus arquivos.
E o debian é muito usado, então as configurações foram bem testadas,
Qual é o objetivo de verificar se o PS1 está definido?
Apenas para descobrir se o shell é interativo.
O padrão
/etc/profile
no debian e no ubuntu (de / usr / share / arquivos-base / perfil):O if é lido: se interativo (conjunto padrão do PS1) e é um shell bash (mas não atua como padrão
sh
), altere o PS1 para um novo em particular (não o padrão).O padrão
/etc/bash.bashrc
no debian também contém:O que é bastante claro no que faz: se interativo, não faça a fonte (o resto).
No entanto, em
/etc/skel/.bashrc
é um exemplo da forma correcta de teste para uma concha interactivo (utilizando$-
):Isso deve mostrar claramente o porquê do PS1 e uma alternativa.
A ordem correta
A configuração que você está relatando deve ser evitada.
A ordem (de configurações do sistema para mais definições específicas do usuário (para bash)) é
/etc/profile
,/etc/bash.bashrc
,~/.profile
e, finalmente~/.bashrc
. Isso coloca os efeitos mais amplos (e para mais shells) em/etc/profile
(que pertence à raiz), seguido por/etc/bash.bashrc
(que também pertence à raiz), mas afeta apenas o bash. Em seguida, entram as configurações pessoais$HOME
, a primeira é~/.profile
para a maioria das conchas e~/.bashrc
(quase equivalente a~/.bash_profile
), específica apenas para o bash.Por isso, é errada a fonte
~/.bashrc
em~/.profile
, ele está transformando uma configuração para a festança de uma forma mais geral que é usuário específico afetando mais conchas . Exceto se feito desta maneira :Ele verifica se o bash está em execução e só carrega
.bashrc
se for esse o caso.Esta é uma decisão upstream vinda do Debian. A lógica é explicada aqui .
Na verdade, o inverso, o abastecimento
~/.profile
em~/.bash_profile
(ou~/.bashrc
) só é re-aplicação de regras gerais que devem ter sido já carregados para um caso de uso particular, e, portanto, "não é tão ruim" (não estou dizendo "bom"). E não estou dizendo bom, porque isso pode causar um loop no fornecimento de arquivos. Como quando um subdiretório carrega um pai, isso é um loop de diretório.E é nessa fonte cruzada que a verificação do shell interativo faz sentido. Somente quando um shell é interativo é
~/.bashrc
carregado, mas por sua vez, ele pode estar carregando~/.profile
(ou vice-versa) e é nesse caso que a verificação de um shell interativo pode ser usada.fonte