Gli script in /etc/profile.d vengono ignorati?


61

Sono nuovo di Ubuntu. Sono in esecuzione 13.10 Desktop.

Volevo impostare alcuni alias di sistema e un prompt personalizzato per bash. Ho trovato questo articolo:

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

Seguendo i consigli di questo articolo, ho creato /etc/profiles.d/profile_local.sh. È di proprietà di root e ha i permessi di 644 proprio come gli altri script 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

Ho ulteriormente confermato che / etc / profile chiama /etc/profile.d. Contiene questo blocco di codice:

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

All'accesso, non sembra che lo script personalizzato, profile_local.sh che ho creato venga fornito. Tuttavia se dopo il login 'source /etc.profile.d/profile_local.sh', ottengo il comportamento previsto, i miei alias personalizzati e il prompt personalizzato.

Che cosa sto facendo di sbagliato?

Contenuto dello 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

1
No, non è eseguibile ma nemmeno gli altri due script. Tuttavia l'ho modificato e riprovato. Ancora niente fortuna.
Estratto il

3
Questo non ha nulla a che fare con l'aggiunta .sh, è irrilevante e comunque i file profile.dsono di provenienza, non eseguiti che è leggermente diverso e non richiede che il file sia eseguibile. Il problema qui è che profile& co non sono letti da script non di accesso.
terdon

1
Drew, leggi la mia risposta. I file di profilo vengono ignorati da shell non di accesso, ma l'accesso alla GUI predefinito di Ubuntu ne leggerà alcuni. Basta usare .bashrce tutti i tuoi problemi spariranno. C'è anche una domanda di precedenza, se uno dei file letti successivamente imposta anche PS1, il valore precedente verrà scartato. Comunque, seriamente, non toccare i filer /etc, gioca con quelli nella tua home directory e .bashrcnon usare il profilo.
terdon

1
Sì, quella dovrebbe essere una shell di login (è il tipo di cosa che dovresti includere nella prossima domanda). Tuttavia, la maggior parte dei sistemi ha .profilefile predefiniti a casa tua e le impostazioni lì sovrascriveranno qualsiasi cosa tu faccia /etc/profile. Fondamentalmente non toccare mai/etc se non sai cosa stai facendo. Ecco a cosa servono i file specifici dell'utente. Inoltre, modifica la tua domanda e spiega esattamente come ti stai connettendo, che cambia tutto.
terdon

4
Si prega di non farlo usando /etc/profile.dquesta è una pessima idea e interesserà tutti gli utenti del sistema. Basta inserire i comandi da profile_local.shnel vostro ~/.profileo semplicemente di risalire allo script aggiungendo questa riga al vostro ~/.profile: . /path/to/profile_local.sh. (il che .significa sourceche leggerà il file che gli dai ed eseguirà i comandi che trova lì).
terdon

Risposte:


109

Per capire cosa sta succedendo qui, è necessario comprendere alcune informazioni di base su come vengono eseguite le shell (bash in questo caso).

  • Quando si apre un emulatore di terminale ( gnome-terminalad esempio), si esegue quella che è nota come shell interattiva senza accesso .

  • Quando si accede al computer dalla riga di comando, tramite ssho si esegue un comando come su - username, si esegue una shell di accesso interattiva .

  • Quando accedi graficamente, stai eseguendo qualcosa di completamente diverso, i dettagli dipenderanno dal tuo sistema e ambiente grafico ma in generale è la shell grafica che si occupa del tuo login. Mentre molte shell grafiche (incluso il default di Ubuntu) leggeranno /etc/profilenon tutte lo fanno.

  • Infine, quando si esegue uno script di shell, viene eseguito in una shell non interattiva e non di accesso .

Ora, i file che bash leggeranno all'avvio dipendono dal tipo di shell su cui è in esecuzione. Quello che segue è un estratto della sezione INVOCATION di man bash(sottolineatura mia):

Quando bash viene invocato come shell di login interattiva o come shell non interattiva con l'opzione --login, legge prima ed esegue i comandi dal file / etc / profile , se quel file esiste. Dopo aver letto quel file, cerca ~ / .bash_profile, ~ / .bash_login e ~ / .profile, in quell'ordine , e legge ed esegue i comandi dal primo che esiste ed è leggibile. L'opzione --noprofile può essere usata all'avvio della shell per inibire questo comportamento.

Quando viene avviata una shell interattiva che non è una shell di accesso , bash legge ed esegue i comandi da /etc/bash.bashrc e ~ / .bashrc , se questi file esistono. Questo può essere inibito usando l'opzione --norc. L'opzione --rcfile forzerà bash a leggere ed eseguire comandi dal file anziché /etc/bash.bashrc e ~ / .bashrc.

Ciò significa che stai modificando il file sbagliato. Puoi testarlo passando a una console virtuale usando Ctrl+ Alt+ F2(torna alla GUI con Alt+ F7, o in F8base alla tua configurazione) e accedendo lì. Vedrai che il tuo prompt e i tuoi alias sono disponibili.

Quindi, al fine di avere l'impostazione che si desidera applicare alle shell non di accesso, il tipo che si ottiene ogni volta che si apre un terminale, è necessario apportare le modifiche ~/.bashrc. In alternativa, puoi anche inserire i tuoi alias nel file ~/.bash_aliases(tuttavia, nota che questa è una funzionalità di Ubuntu e non dovresti aspettarti che funzioni su altre distribuzioni).

Per maggiori dettagli su quale file utilizzare per cosa, vedere qui .


APPUNTI:

  • Debian (e per estensione Ubuntu) ha anche la ~/.profilefonte predefinita ~/.bashrc. Ciò significa che qualsiasi modifica apportata ~/.bashrcverrà ereditata anche dalle shell di login, ma i) questo non è il caso in tutte le macchine Linux / Unix e ii) l'inverso non è vero, motivo per cui generalmente dovresti sempre lavorare con ~/.bashrc& co anziché ~/.profileo /etc/profile.

  • Inoltre, una nota generale sull'uso, le modifiche apportate ai file di configurazione /etcinteresseranno tutti gli utenti. Questo di solito non è quello che vuoi fare e dovrebbe essere evitato. Dovresti sempre usare i file equivalenti nella tua home directory ( ~/).

  • I vari file di configurazione vengono letti in sequenza. In particolare, per le shell di login, l'ordine è:

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

    Ciò significa che qualsiasi impostazione in ~/.profilesovrascriverà qualsiasi cosa impostata nei file precedenti.


1
Secondo questo post howtolamp.com/articles/… , puoi anche eseguire echo $0da un terminale e se l'output ha il prefisso "-", allora sei in una shell di login.
StackOverflower

@stackoverflower non è sul mio sistema. Funziona con una shell di login remota e interattiva. Non sembra quando si corre bash -l. In ogni caso, perché è rilevante? La domanda non è su come verificare quale tipo di shell si sta eseguendo.
terdon

post magnifico, mi chiedo perché non sia apparso su Google quando ho avuto lo stesso problema
Donato,

@stackoverflower Se si "$0"espande in qualcosa che inizia con -, allora sai di avere una shell di login. Ma il contrario non è vero: l'assenza di -non garantisce di non essere in una shell di accesso. I modi più comuni per avviare le shell di accesso ti danno un vantaggio -, ma non tutti. man bashci dice "Una shell di login è quella il cui primo carattere dell'argomento zero è a -, oppure uno è iniziato con l' --loginopzione". ( -lè la forma abbreviata di --login; sono equivalenti .) In Bash puoi correre shopt login_shellper controllare.
Eliah Kagan,

2

Un'altra possibilità, soprattutto per le impostazioni come le impostazioni della cronologia HISTSIZE, HISTFILESIZE, HISTCONTROL, ed PS1è che i file vengono caricati, ma le impostazioni vengono sovrascritte in un altro file che è di origine più tardi, con la causa più probabile di essere ~/.bashrc. (Ho un set predefinito di impostazioni per i nostri server, come un prompt che è rosso per root per avvisare l'utente e grandi storie con timestamp)

Ubuntu predefinito .bashrcda /etc/skelimposta diverse impostazioni, che potrebbe avere senso impostare da qualche parte in cui non sovrascriverebbe le impostazioni impostate dal proprietario del sistema da /etc/profile.d(Mi piace /etc/bash.bashrc) (Se un utente modifica le proprie .bashrc, va bene sovrascrivere le impostazioni, i file predefiniti del sistema sono più fastidiosi)


2

nella sessione di Debian per Terminal ho risolto questo problema per tutti gli utenti, quindi:

aggiunto a

sudo nano /etc/bash.bashrc

bloccare

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

a partire dal

/etc/profile

1

Segui questo percorso:

  • Apri Modifica -> Preferenze
  • Nella prima scheda "Generale", sotto l'etichetta "Comando", abilita "Esegui comando come shell di accesso"

-1

VERSIONE = "16.04.3 LTS (Xenial Xerus)"

Ok, quindi tutti hanno supposto che la persona qui non voglia /etc/profile.d/somefile.sh per tutti gli utenti, ma nel mio caso è esattamente quello che volevo.

Quindi, in realtà, come risulta con Ubuntu se lo usi e vuoi che abbia effetto nella tua shell grafica, tutto ciò che devi fare è impostare il file e quindi disconnetterti e riconnetterti. Tutte le tue console o tutto ciò che avvii, sia esso di tipo xterm o di tipo console (o rilasciandolo sulla shell) ora avrà quel file di provenienza.

Non è necessario utilizzare .bashrc ecc. Per tutti gli utenti. Mi dispiace, questo non era chiaro nella risposta sopra. Tutto ciò che hanno detto è vero, ma in realtà non è vero, dato che tutto ciò che viene avviato da Windows Manager erediterà queste impostazioni, quindi basta accedere nuovamente e risolvere il problema e non preoccuparsi di .bashrc ecc. Se si intende applicarlo a tutti gli utenti .


2
Il mio problema è esattamente che ciò non accade nel terminale eseguito sotto l'interfaccia utente grafica; né in Ubuntu 16.04.3 o 18.04.
Thomas Arildsen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.