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 / 462663
Accepted
shotes
shotes
Asked: 2018-08-15 20:40:38 +0800 CST2018-08-15 20:40:38 +0800 CST 2018-08-15 20:40:38 +0800 CST

Objetivo de [ -n "$PS1" ] no bashrc

  • 772

Para que serve o [ -n "$PS1" ]in [ -n "$PS1" ] && source ~/.bash_profile;? Esta linha está incluída em um repositório.bashrc dotfiles .

bash osx
  • 4 4 respostas
  • 3631 Views

4 respostas

  • Voted
  1. Best Answer
    filbranden
    2018-08-15T20:57:59+08:002018-08-15T20:57:59+08:00

    Isso está verificando se o shell é interativo ou não. Nesse caso, apenas forneça o ~/.bash_profilearquivo se o shell for interativo.

    Consulte "Este Shell é interativo?" no manual do bash, que cita esse idioma específico. (Ele também recomenda verificar se o shell é interativo testando se a $-variável especial contém o icaractere, o que é uma abordagem melhor para esse problema.)

    • 22
  2. Gilles 'SO- stop being evil'
    2018-08-15T22:31:07+08:002018-08-15T22:31:07+08:00

    O que isso faz

    Essa é uma maneira generalizada de testar se o shell é interativo. Cuidado que só funciona no bash, não funciona com outros shells. Então está tudo bem (se bobo) para .bashrc, mas não funcionaria em .profile(que é lido por sh, e bash é apenas uma das implementações possíveis de sh, e não a mais comum).

    Por que funciona (somente no bash!)

    Um shell interativo define a variável shellPS1 para a string de prompt padrão. Portanto, se o shell for interativo, PS1está definido (a menos que o usuário o .bashrctenha removido, o que ainda não pode ter acontecido no topo de .bashrc, e você pode considerar que é uma coisa boba de se fazer de qualquer maneira).

    O inverso é verdadeiro no bash: instâncias não interativas do bash não são definidas PS1quando são iniciadas. Observe que esse comportamento é específico do bash e é sem dúvida um bug (por que bash -c '… do stuff with $var…'não funcionaria quando varé PS1?). Mas todas as versões do bash até e incluindo 4.4 (a versão mais recente enquanto escrevo) fazem isso.

    Muitos sistemas exportam PS1para o ambiente. É uma má idéia, porque muitos shells diferentes usam, PS1mas com uma sintaxe diferente (por exemplo , os escapes do prompt do bash são completamente diferentes dos escapes do prompt do zsh ). Mas é difundido o suficiente para que, na prática, ver que PS1está definido não seja um indicador confiável de que o shell é interativo. O shell pode ter herdado PS1do ambiente.

    Por que é (mal) usado aqui

    .bashrcé o arquivo que o bash lê na inicialização quando é interativo. Um fato menos conhecido é que o bash também lê .bashrcum shell de login e a heurística do bash conclui que esta é uma sessão remota (o bash verifica se seu pai é rshdou sshd). Neste segundo caso, é improvável que PS1isso seja definido no ambiente, porque nenhum arquivo dot foi executado ainda.

    No entanto, a maneira como o código usa essas informações é contraproducente.

    • Se o shell for um shell interativo, ele será executado .bash_profilenesse shell. Mas .bash_profileé um script de tempo de login. Ele pode executar alguns programas que devem ser executados apenas uma vez por sessão. Ele 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_profileem um shell sem login é disruptiva.
    • Se o shell for um shell de login remoto não interativo, ele não carregará .bash_profile. Mas este é o caso em que o carregamento .bash_profilepode ser útil, porque um shell de login não interativo não carrega automaticamente /etc/profilee arquivos ~/.profile.

    Acho que a razão pela qual as pessoas fazem isso é para usuários que fazem login por meio de uma GUI (um caso muito comum) e que colocam suas configurações de variáveis ​​de ambiente em .bash_profilevez de .profile. A maioria dos mecanismos de login da GUI invoca, .profilemas não .bash_profile(a leitura .bash_profileexigiria a execução do bash como parte da inicialização da sessão, em vez de sh). Com essa configuração, ao abrir um terminal, o usuário obterá suas variáveis ​​de ambiente. No entanto, o usuário não obterá suas variáveis ​​de ambiente em aplicativos GUI, o que é uma fonte muito comum de confusão. A solução aqui é usar .profileem vez de .bash_profiledefinir variáveis ​​de ambiente. Adicionar uma ponte entre .bashrce .bash_profilecria 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 -iestá habilitada.

    case $- in
      *i*) echo "This shell is interactive";;
      *) echo "This shell is not interactive";;
    esac
    

    Isso é útil .bashrcpara ler .profileapenas se o shell não for interativo - ou seja, o oposto do que o código faz! Leia .profilese o bash for um shell de login (não interativo) e não o leia se for um shell interativo.

    if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
    
    • 22
  3. schily
    2018-08-16T01:41:10+08:002018-08-16T01:41:10+08:00

    Parece que esse conceito estranho é resultado do fato de que bashnão começou como um clone do shell POSIX, mas como um Bourne Shellclone.

    Como resultado, o comportamento interativo POSIX ( $ENVé chamado para shells interativos) foi adicionado posteriormente bashe não é amplamente conhecido.

    Há um shell que concede um comportamento semelhante. Isso é cshe csh grants que $prompttem valores específicos:

    $prompt not set          non-interactive shell, test $?prompt.
    $prompt set but == ""    .cshrc called by the which(1) command.
    $prompt set and != ""    normal interactive shell.
    

    Mas isso não se aplica ao Bourne Shell nem aos shells POSIX.

    Para um shell POSIX, o único método concedido é colocar código para shells interativos no arquivo:

    $ENV
    

    que tem um nome específico de shell. É por exemplo

    $HOME/.kshrc    for the korn shell
    $HOME/.bashrc   for bash
    $HOME/.mkshrc   for mksh
    $HOME/.shrc     for the POSIX Bourne Shell
    

    Outras pessoas mencionaram o sinalizador de shell -i, mas isso não é útil para programação confiável. O POSIX não requer que set -ifuncione, nem que $-contenha um ipara shells interativos. POSIX apenas requer que imponha sh -io shell no modo interativo.

    Como a variável $PS1pode ser importada do ambiente, ela pode ter um valor mesmo no modo não interativo. O fato de que bash unsets PS1em qualquer shell não interativo não é concedido pelo padrão e não é feito por nenhum outro shell.

    Portanto, programação limpa (mesmo com bash) é colocar os comandos para shells interativos em $HOME/.bashrc.

    • 2
  4. user232326
    2018-08-18T19:31:29+08:002018-08-18T19:31:29+08:00

    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 inicialização do shell, há muita opinião.
    Também tenho minha opinião, mas tentarei mostrar exemplos existentes de configurações corretas.
    Vou usar o debuan, pois é bem 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/profileno debian e no ubuntu (de /usr/share/base-files/profile):

    if [ "${PS1-}" ]; then
        if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
    

    O if é lido: se interativo (conjunto padrão do PS1) e é um shell bash (mas não atuando como padrão sh), altere o PS1 para um novo específico (não o padrão).

    O padrão /etc/bash.bashrcno debian também contém:

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

    O que é bastante claro no que faz: se interativo, não fonte (o resto).

    No entanto, in /etc/skel/.bashrcé um exemplo da maneira correta de testar um shell interativo (usando $-):

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

    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 (das configurações do sistema para configurações de usuário mais específicas (para bash)) é /etc/profile, /etc/bash.bashrce ~/.profilefinalmente ~/.bashrc. Isso coloca os efeitos mais amplos (e para mais shells) em /etc/profile(que é de propriedade do root) seguido por /etc/bash.bashrc(que também é de propriedade do root), mas afeta apenas o bash. Em seguida, vêm as configurações pessoais em $HOME, a primeira é ~/.profilepara a maioria dos shells e ~/.bashrc(quase equivalente a ~/.bash_profile), específica apenas para o bash.

    Portanto, é errado originar , está transformando uma configuração de usuário específica para bash em uma mais geral que está ~/.bashrcafetando mais shells . Exceto se feito desta forma :~/.profile

    # ~/.profile: executed by the command interpreter for login shells
    # if running bash
    if [ -n "$BASH_VERSION" ]; then
        # include .bashrc if it exists
        if [ -f "$HOME/.bashrc" ]; then
        . "$HOME/.bashrc"
        fi
    fi
    

    Ele verifica se o bash está em execução e carrega apenas .bashrcse for o caso.

    Esta é uma decisão upstream vinda do Debian. A razão é explicada aqui .

    Na verdade, o inverso, sourcing ~/.profileem ~/.bash_profile(ou ~/.bashrc) está apenas reaplicando regras gerais que já deveriam ter sido carregadas para um caso de uso específico e, portanto, "não é tão ruim" (não estou dizendo "bom"). E não estou dizendo bem porque isso pode fazer com que a fonte de arquivos entre em loop. Como quando um subdiretório carrega um pai, isso é um loop de diretório.

    E é nesse cruzamento de fontes que a verificação do shell interativo faz sentido. Somente quando um shell é interativo é ~/.bashrccarregado, mas por sua vez pode estar carregando ~/.profile(ou vice-versa) e é neste caso que a verificação de um shell interativo pode ser usada.

    • 1

relate perguntas

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

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

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

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

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 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

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 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
    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
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +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
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +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