Scripts em /etc/profile.d sendo ignorados?

61

Eu sou novo no Ubuntu. Estou executando o 13.10 Desktop.

Eu queria definir alguns aliases para todo o sistema e um prompt personalizado para o bash. Encontrei este artigo:

https://help.ubuntu.com/community/EnvironmentVariables

Seguindo os conselhos deste artigo, criei o /etc/profiles.d/profile_local.sh. É de propriedade do root e tem permissões de 644, assim como os outros scripts de lá:

root@ubuntu:/etc/profile.d# ll
total 28
drwxr-xr-x   2 root root  4096 Mar 23 08:56 .
drwxr-xr-x 135 root root 12288 Mar 23 09:15 ..
-rw-r--r--   1 root root   660 Oct 23  2012 bash_completion.sh
-rw-r--r--   1 root root  3317 Mar 23 07:36 profile_local.sh
-rw-r--r--   1 root root  1947 Nov 23 00:57 vte.sh

Confirmei ainda que o / etc / profile chama /etc/profile.d. Ele contém este bloco de código:

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

No login, não parece que o script personalizado profile_local.sh que eu criei tenha origem. No entanto, se após o login eu 'origem /etc.profile.d/profile_local.sh', obtenho o comportamento esperado, meus aliases personalizados e prompt personalizado.

O que estou fazendo errado?

Conteúdo do script 'profile_local.sh':

# 3/23/14 - Copied from Gentoo /etc/bash/bashrc
# Placed in /etc/profile.d as described at:
# https://help.ubuntu.com/community/EnvironmentVariables

# This file is sourced by all *interactive* bash shells on startup,
# including some apparently interactive shells such as scp and rcp
# that can't tolerate any output.  So make sure this doesn't display
# anything or bad things will happen !


# Test for an interactive shell.  There is no need to set anything
# past this point for scp and rcp, and it's important to refrain from
# outputting anything in those cases.
if [[ $- != *i* ]] ; then
        # Shell is non-interactive.  Be done now!
        return
fi

# Bash won't get SIGWINCH if another process is in the foreground.
# Enable checkwinsize so that bash will check the terminal size when
# it regains control.  #65623
# http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11)
shopt -s checkwinsize

# Enable history appending instead of overwriting.  #139609
shopt -s histappend

# Change the window title of X terminals 
case ${TERM} in
        xterm*|rxvt*|Eterm|aterm|kterm|gnome*|interix)
                PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\007"'
                ;;
        screen)
                PROMPT_COMMAND='echo -ne "\033_${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/~}\033\\"'
                ;;
esac

use_color=false

# Set colorful PS1 only on colorful terminals.
# dircolors --print-database uses its own built-in database
# instead of using /etc/DIR_COLORS.  Try to use the external file
# first to take advantage of user additions.  Use internal bash
# globbing instead of external grep binary.
safe_term=${TERM//[^[:alnum:]]/?}   # sanitize TERM
match_lhs=""
[[ -f ~/.dir_colors   ]] && match_lhs="${match_lhs}$(<~/.dir_colors)"
[[ -f /etc/DIR_COLORS ]] && match_lhs="${match_lhs}$(</etc/DIR_COLORS)"
[[ -z ${match_lhs}    ]] \
        && type -P dircolors >/dev/null \
        && match_lhs=$(dircolors --print-database)
[[ $'\n'${match_lhs} == *$'\n'"TERM "${safe_term}* ]] && use_color=true

if ${use_color} ; then
        # Enable colors for ls, etc.  Prefer ~/.dir_colors #64489
        if type -P dircolors >/dev/null ; then
                if [[ -f ~/.dir_colors ]] ; then
                        eval $(dircolors -b ~/.dir_colors)
                elif [[ -f /etc/DIR_COLORS ]] ; then
                        eval $(dircolors -b /etc/DIR_COLORS)
                fi
        fi

        if [[ ${EUID} == 0 ]] ; then
                PS1='\[\033[01;31m\]\h\[\033[01;34m\] \W \$\[\033[00m\] '
        else
                PS1='\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\] '
        fi

        alias ls='ls --color=auto'
        alias grep='grep --colour=auto'
else
        if [[ ${EUID} == 0 ]] ; then
                # show root@ when we don't have colors
                PS1='\u@\h \W \$ '
        else
                PS1='\u@\h \w \$ '
        fi
fi

# Try to keep environment pollution down, EPA loves us.
unset use_color safe_term match_lhs

TZ="PST8PDT"

alias ll='ls -la'
alias dig='dig +search'
alias dir='ls -ba'

alias edit="ee"
alias ss="ps -aux"
alias dot='ls .[a-zA-Z0-9_]*'
alias news="xterm -g 80x45 -e trn -e -S1 -N &"

alias more="less"
alias c="clear"
alias m="more"
alias j="jobs"

# common misspellings
alias mroe=more
alias pdw=pwd
Desenhou
fonte
11
Não, não é executável, mas os outros dois scripts também não. No entanto, eu mudei e tentei novamente. Ainda sem sorte.
Tirou
3
Isso não tem nada a ver com a adição .sh, é irrelevante e, de qualquer forma, os arquivos profile.dsão originados, não executados, o que é um pouco diferente e não exige que o arquivo seja executável. O problema aqui é que o profile& co não é lido por scripts que não são de login.
terdon
11
Drew, leia minha resposta. Os arquivos de perfil são ignorados por shells que não são de login, mas o login GUI padrão do Ubuntu lerá alguns deles. Basta usar .bashrce todos os seus problemas desaparecerão. Há também uma questão de precedência, se um dos arquivos lidos posteriormente também definir o PS1, o valor anterior será descartado. De qualquer forma, sério, não toque nos arquivadores /etc, brinque com os diretores de sua casa e .bashrcnão use perfis.
terdon
11
Sim, esse deve ser um shell de login (esse é o tipo de coisa que você deve incluir na sua pergunta da próxima vez). No entanto, a maioria dos sistemas possui .profilearquivos padrão em sua casa e as configurações substituem tudo o que você faz /etc/profile. Basicamente, nunca toque a /etcmenos que você saiba o que está fazendo. É para isso que servem os arquivos específicos do usuário. Além disso, edite sua pergunta e explique exatamente como você está se conectando, isso muda tudo.
terdon
4
Por favor, não faça isso usando /etc/profile.duma péssima idéia e afetará todos os usuários do sistema. Basta incluir os comandos profile_local.shna sua ~/.profileou simplesmente fonte o script, adicionando esta linha ao seu ~/.profile: . /path/to/profile_local.sh. (o .meio source, ele lerá o arquivo que você fornecer e executará os comandos que encontrar lá).
terdon

Respostas:

109

Para entender o que está acontecendo aqui, você precisa entender algumas informações básicas sobre como os shells (neste caso, o bash) são executados.

  • Quando você abre um emulador de terminal ( gnome-terminalpor exemplo), está executando o que é conhecido como um shell interativo sem logon .

  • Quando você faz login na sua máquina a partir da linha de comando, via sshou executa um comando como su - username, você está executando um shell de logon interativo .

  • Quando você efetua login graficamente, está executando algo completamente diferente, os detalhes dependerão do sistema e do ambiente gráfico, mas, em geral, é o shell gráfico que lida com o seu login. Embora muitos shells gráficos (incluindo o padrão do Ubuntu) leiam, /etc/profilenem todos eles fazem.

  • Finalmente, quando você executa um script de shell, ele é executado em um shell não interativo e sem logon .

Agora, os arquivos que o bash lerá quando iniciado dependem do tipo de shell em que está sendo executado. A seguir, um trecho da seção INVOCATION de man bash(ênfase minha):

Quando o bash é chamado como um shell de login interativo ou como um shell não interativo com a opção --login, ele primeiro lê e executa comandos do arquivo / etc / profile , se esse arquivo existir. Depois de ler esse arquivo, ele procura ~ / .bash_profile, ~ / .bash_login e ~ / .profile, nessa ordem , e lê e executa comandos do primeiro que existe e é legível. A opção --noprofile pode ser usada quando o shell é iniciado para inibir esse comportamento.

Quando um shell interativo que não é um shell de login é iniciado, o bash lê e executa comandos de /etc/bash.bashrc e ~ / .bashrc , se esses arquivos existirem. Isso pode ser inibido usando a opção --norc. A opção --rcfile file forçará o bash a ler e executar comandos do arquivo, em vez de /etc/bash.bashrc e ~ / .bashrc.

O que tudo isso significa é que você está editando o arquivo errado. Você pode testar isso acessando um console virtual usando Ctrl+ Alt+ F2(retorne à GUI com Alt+ F7, ou F8dependendo da sua configuração) e fazendo login. Você verá que seu prompt e alias estão disponíveis.

Portanto, para ter a configuração que você deseja aplicar aos shells que não são de login, o tipo que você obtém toda vez que abre um terminal, deve fazer suas alterações ~/.bashrc. Como alternativa, você também pode colocar seus aliases no arquivo ~/.bash_aliases(no entanto, observe que esse é um recurso do Ubuntu e você não deve esperar que ele funcione em outras distribuições).

Para mais detalhes sobre qual arquivo deve ser usado, veja aqui .


NOTAS:

  • O Debian (e por extensão o Ubuntu) também tem a ~/.profilefonte padrão ~/.bashrc. Isso significa que todas as alterações que você fizer ~/.bashrctambém serão herdadas pelos shells de login, mas i) esse não é o caso em todas as máquinas Linux / Unix e ii) o inverso não é verdadeiro, e é por isso que você geralmente sempre deve trabalhar com ~/.bashrc& co em vez de ~/.profileou /etc/profile.

  • Além disso, uma observação geral sobre o uso, as alterações feitas nos arquivos de configuração /etcafetarão todos os usuários. Isso geralmente não é o que você deseja fazer e deve ser evitado. Você sempre deve usar os arquivos equivalentes em seu diretório pessoal ( ~/).

  • Os vários arquivos de configuração são lidos sequencialmente. Especificamente, para shells de login, o pedido é:

    /etc/profile -> /etc/profile.d/* (in alphabetical order) -> ~/.profile

    Isso significa que qualquer configuração ~/.profilesubstituirá qualquer coisa definida nos arquivos anteriores.

terdon
fonte
11
De acordo com este post , howtolamp.com/articles/… , você também pode executar a echo $0partir de um terminal e, se a saída tiver o prefixo "-", você estará em um shell de login.
stackoverflower
@stackoverflower não está no meu sistema. Isso funciona para um shell de login remoto e interativo. Não parece quando em execução bash -l. De qualquer forma, por que isso é relevante? A questão não é sobre como verificar que tipo de shell você está executando.
terdon
pós magnificant, me pergunto por que não apareceu no google quando eu tive o mesmo problema
Donato
@stackoverflower Se se "$0"expandir para algo que começa com -, então você sabe que possui um shell de login. Mas o inverso não é verdadeiro: a ausência de -não garante que você não esteja em um shell de login. As formas mais comuns de iniciar shells de login fornecem uma liderança -, mas não todas. man bashnos diz "Um shell de login é aquele cujo primeiro caractere do argumento zero é a -ou iniciou com a --loginopção". ( -lé a forma abreviada de --login; eles são equivalentes .) No Bash, você pode executar shopt login_shella verificação.
Eliah Kagan
2

Outra possibilidade, especialmente para configurações, como as configurações de histórico HISTSIZE, HISTFILESIZE, HISTCONTROL, e PS1é que os arquivos estão sendo carregados, mas as configurações são substituídas em outro arquivo que é a fonte mais tarde, com o culpado mais provável de ser ~/.bashrc. (Eu tenho um conjunto padrão de configurações para nossos servidores, como um prompt vermelho para root para avisar o usuário e grandes históricos com registros de data e hora)

O padrão do Ubuntu .bashrca partir de /etc/skelconjuntos de várias configurações, o que pode ter feito sentido para definir de algum lugar onde não substituem as configurações definidas pelo proprietário do sistema a partir de /etc/profile.d(Like /etc/bash.bashrc) (Se um usuário edita o seu .bashrc, é bom para substituir configurações, os arquivos padrão do sistema são mais irritantes)

Gert van den Berg
fonte
2

na sessão Debian para Terminal, resolvi esse problema para todos os usuários, de modo que:

Adicionado a

sudo nano /etc/bash.bashrc

quadra

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

de

/etc/profile
Nikolay Baranenko
fonte
1

Siga este caminho:

  • Abra Editar -> Preferências
  • Na primeira guia "Geral", sob o rótulo "Comando", ative "Executar comando como shell de login"
Mac
fonte
-1

VERSÃO = "16.04.3 LTS (Xenial Xerus)"

Ok, então todos assumiram que a pessoa aqui não quer /etc/profile.d/somefile.sh para todos os usuários, mas, no meu caso, é exatamente isso que eu queria.

Então, na verdade, como acontece com o Ubuntu, se você usar isso e quiser que ele entre em vigor no seu shell gráfico, tudo o que você precisa fazer é definir o arquivo e, em seguida, efetuar logout e logon novamente. Todos os seus consoles ou qualquer coisa que você iniciar, seja do tipo xterm ou do console (ou seja, solte no shell) agora terão esse arquivo originado.

Não há necessidade de usar .bashrc etc para todos os usuários. Desculpe, mas isso não ficou claro na resposta acima. Tudo o que eles disseram é verdade, mas, na verdade, na maioria das vezes não é verdade, pois tudo o que o gerenciador do Windows lança herdará essas configurações. Basta fazer login novamente e resolver o problema e não se preocupar com o .bashrc etc., se sua intenção é aplicá-lo a todos os usuários. .

Isaac Kane Egglestone
fonte
2
Meu problema é exatamente que isso não acontece no terminal executado sob a interface gráfica do usuário; nem no Ubuntu 16.04.3 ou 18.04.
Thomas Arildsen