Differenza tra .bashrc e .bash_profile


449

Qual è la differenza tra .bashrce .bash_profilee quale dovrei usare?



Se vuoi una spiegazione più completa che implichi anche .profile, dai un'occhiata a questa domanda: superuser.com/questions/789448/…
Flimm

Questa risposta copre anche alcuni aspetti stackoverflow.com/questions/415403/…
Sergey Voronezhskiy,

Risposte:


517

Tradizionalmente, quando si accede a un sistema Unix, il sistema avvia un programma per te. Quel programma è una shell, cioè un programma progettato per avviare altri programmi. È una shell della riga di comando: si avvia un altro programma digitandone il nome. La shell predefinita, una shell Bourne, legge i comandi da ~/.profilequando viene invocata come shell di accesso.

Bash è una shell tipo Bourne. Legge i comandi da ~/.bash_profilequando viene invocato come shell di accesso e se quel file non esiste¹, prova ~/.profileinvece a leggere .

È possibile richiamare una shell direttamente in qualsiasi momento, ad esempio avviando un emulatore di terminale all'interno di un ambiente GUI. Se la shell non è una shell di accesso, non legge ~/.profile. Quando si avvia bash come shell interattiva (ovvero, per non eseguire uno script), si legge ~/.bashrc(tranne quando viene invocato come shell di login, quindi legge solo ~/.bash_profileo ~/.profile.

Perciò:

  • ~/.profile è il luogo in cui inserire elementi che si applicano all'intera sessione, ad esempio i programmi che si desidera avviare quando si accede (ma non i programmi grafici, entrano in un file diverso) e le definizioni delle variabili di ambiente.

  • ~/.bashrcè il posto dove mettere cose che si applicano solo a bash stesso, come alias e definizioni di funzioni, opzioni di shell e impostazioni di prompt. (Potresti anche inserire combinazioni di tasti lì, ma per bash normalmente entrano ~/.inputrc.)

  • ~/.bash_profilepuò essere usato al posto di ~/.profile, ma viene letto solo da bash, non da qualsiasi altra shell. (Questo è principalmente un problema se vuoi che i tuoi file di inizializzazione funzionino su più macchine e la tua shell di login non bash su tutti loro.) Questo è un posto logico da includere ~/.bashrcse la shell è interattiva. Raccomando i seguenti contenuti in ~/.bash_profile:

    if [ -r ~/.profile ]; then . ~/.profile; fi
    case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

Sui moderni unice, c'è un'ulteriore complicazione correlata ~/.profile. Se accedi in un ambiente grafico (ovvero, se il programma in cui digiti la password è in esecuzione in modalità grafica), non otterrai automaticamente una shell di accesso che legge ~/.profile. A seconda del programma di accesso grafico, del gestore di finestre o dell'ambiente desktop che esegui in seguito e di come la tua distribuzione ha configurato questi programmi, ~/.profilepuoi leggere o meno. In caso contrario, di solito c'è un altro posto in cui è possibile definire variabili di ambiente e programmi da avviare quando si accede, ma purtroppo non esiste una posizione standard.

Nota che puoi vedere qui e là consigli per inserire definizioni delle variabili di ambiente ~/.bashrco avviare sempre shell di login nei terminali. Entrambe sono cattive idee. Il problema più comune con una di queste idee è che le variabili di ambiente verranno impostate solo nei programmi avviati tramite il terminale, non nei programmi avviati direttamente con un'icona o un menu o una scorciatoia da tastiera.

¹ Per completezza, su richiesta: se .bash_profilenon esiste, bash prova anche .bash_loginprima di tornare a .profile. Sentiti libero di dimenticare che esiste.


11
+1 per un buon post. Grazie anche per aver aggiunto la sezione "login grafico vs login shell" ... Ho avuto il problema in cui pensavo che ~ / .profile sarebbe SEMPRE eseguito per grafico / shell ... ma non viene eseguito quando l'utente accede tramite login grafico. Grazie per aver risolto quel mistero.
Trevor Boyd Smith,

4
@Gilles: Potresti spiegare più dettagliatamente, con esempi, perché eseguire una shell di login in ogni terminale sia una cattiva idea? Questo è solo un problema con Linux desktop? (Capisco che su OS X Terminal esegue una shell di accesso ogni volta e non ho mai notato effetti collaterali (anche se di solito uso iTerm). Ma poi non riesco a pensare a molte variabili di ambiente che mi interesserebbero al di fuori di un terminale. (Forse HTTP_PROXY?))
iconoclast

2
@Brandon Se si esegue una shell di login in ogni terminale, questo sovrascriverà le variabili di ambiente fornite dall'ambiente. Nelle situazioni quotidiane, puoi cavartela, ma verrà e ti morderà prima o poi, quando vuoi impostare diverse variabili in un terminale (diciamo, per provare una versione diversa di un programma): eseguire un la shell di accesso avrebbe la precedenza sulle impostazioni locali.
Gilles,

4
È ~/.bash_profilepossibile utilizzare l'~/.profile~/.bashrc istruzione anziché , ma è necessario includere anche se la shell è interattiva. è fuorviante in quanto si tratta di problemi ortogonali. Non importa se usi ~/.bash_profileo ~/.profiledevi includere ~/.bashrcquello che usi se vuoi che le impostazioni da lì abbiano effetto nella shell di login.
Piotr Dobrogost,

3
@Gilles Certo, ma il modo in cui la frase è formulata nella risposta suggerisce che la necessità di includere ~/.bashrcha a che fare con la scelta ~/.bash_profileinvece ~/.profileche non è vera. Se qualcuno include ~/.bashrcqualsiasi tipo di script che viene fornito al momento dell'accesso (qui è o ~/.bash_profileo ~/.profile) è perché desidera che le impostazioni ~/.bashrcvengano applicate alla shell di accesso nello stesso modo in cui vengono applicate alla shell non di accesso.
Piotr Dobrogost,

53

Da questo breve articolo

Secondo la pagina man di bash, .bash_profile viene eseguito per le shell di login, mentre .bashrc viene eseguito per le shell interattive non di login.

Che cos'è una shell di login o non login?

Quando si accede (ad esempio: digitare nome utente e password) tramite console, sia fisicamente seduto sulla macchina all'avvio, sia da remoto tramite ssh: .bash_profile viene eseguito per configurare le cose prima del prompt dei comandi iniziale.

Ma, se hai già effettuato l'accesso al tuo computer e hai aperto una nuova finestra di terminale (xterm) all'interno di Gnome o KDE, allora .bashrc viene eseguito prima del prompt dei comandi della finestra. .bashrc viene eseguito anche quando si avvia una nuova istanza bash digitando / bin / bash in un terminale.


12
Lievi aggiornamenti: "Eseguito" è probabilmente un termine leggermente fuorviante, entrambi provengono da entrambi. Eseguito suona come se fosse eseguito come uno script, fork / exec yadda yadda. Viene eseguito nel contesto della shell corrente Ancora più importante, .bashrc viene eseguito molto più spesso. Viene eseguito su ogni script bash, e anche se non si dispone di un .bash_profile. Inoltre, a seconda di come hai impostato i tuoi xterm, puoi creare una shell che genera .bash_profile
Rich Homolka

36

Ai vecchi tempi, quando le pseudo-tty non erano pseudo e in realtà, bene, digitate, e UNIX erano accessibili da modem così lenti da poter vedere ogni lettera stampata sullo schermo, l'efficienza era fondamentale. Per aiutare l'efficienza, in qualche modo avevi il concetto di una finestra di accesso principale e di qualsiasi altra finestra in cui funzionavi effettivamente. Nella finestra principale, desideri ricevere notifiche per qualsiasi nuova posta, possibilmente eseguire alcuni altri programmi in background.

A supporto di ciò, le shell hanno fornito un file .profilespecifico su "shell di accesso". Questo farebbe lo speciale, una volta impostato un programma di sessione. Bash lo ha esteso in qualche modo per guardare .bash_profile prima di .profile, in questo modo potresti mettere solo le cose lì dentro (in modo che non rovinino la shell Bourne, ecc., Che hanno anche guardato .profile). Altre shell, senza login, avrebbero solo il sorgente del file rc, .bashrc (o .kshrc, ecc.).

Questo è un po 'un anacronismo ora. Non accedi a una shell principale tanto quanto accedi a un gestore di finestre GUI. Non esiste una finestra principale diversa da qualsiasi altra finestra.

Il mio consiglio: non preoccuparti di questa differenza, si basa su uno stile più vecchio di utilizzo di unix. Elimina la differenza nei tuoi file. L'intero contenuto di .bash_profile dovrebbe essere:

[ -f $HOME/.bashrc ] && . $HOME/.bashrc

E metti tutto ciò che vuoi effettivamente impostare in .bashrc

Ricorda che .bashrc è di provenienza per tutte le shell, interattivo e non interattivo. È possibile cortocircuitare il sourcing per shell non interattive mettendo questo codice nella parte superiore di .bashrc:

[[ $- != *i* ]] && return


6
Questa è una cattiva idea, vedi la mia risposta . In particolare, le variabili di ambiente verranno impostate solo nei programmi avviati tramite il terminale, non nei programmi avviati direttamente con un'icona o un menu o una scorciatoia da tastiera.
Gilles,

4
@Gilles Non capisco perché lo rivendichi. Con .$HOME/.bashrccome Rich ha mostrato in precedenza, le impostazioni in .bashrcsaranno disponibili in shell di login, e, quindi, l'ambiente desktop pure. Ad esempio, sul mio sistema Fedora, gnome-sessionviene avviato come -$SHELL -c gnome-session, quindi .profileviene letto.
Mikel,

2
@PiotrDobrogost Oh, sì, c'è un altro problema con la risposta di Rich. Includere .bashrcin .profilegenere non funziona, perché .profilepuò essere eseguito da /bin/she non bash (ad esempio su Ubuntu per un accesso grafico di default), e quella shell potrebbe non essere interattiva (ad esempio per un accesso grafico).
Gilles,

3
@Gilles re: "incluso .bashrc in .profile" non è affatto ciò che è stato raccomandato (anzi, al contrario). O la risposta è stata modificata (non sembra così), oppure i tuoi commenti non si allineano a ciò che viene detto.
michael

2
In generale, +1, ma aggiungerei alla raccomandazione di "corto circuito ... per shell non interattive" ("vicino alla cima di .bashrc: [[ $- != *i* ]] && return"); Mi piace che alcuni dei miei .bashrcvengano eseguiti anche per shell non interattive, in particolare per impostare env vars, durante l'emissione ssh hostname {command}, in modo che i comandi remoti vengano eseguiti correttamente (anche se la shell non è interattiva). Altre impostazioni successive .bashrcdovrebbero essere ignorate. Di solito cerco TERM = stupido e / o non impostato, quindi eseguo il salvataggio in anticipo.
michael

18

Dai un'occhiata a questo eccellente post sul blog di ShreevatsaR . Ecco un estratto, ma vai al post del blog, include una spiegazione per termini come "login shell", un diagramma di flusso e una tabella simile per Zsh.

Per Bash, funzionano come segue. Leggi la colonna appropriata. Esegue A, quindi B, quindi C, ecc. B1, B2, B3 significa che esegue solo il primo di quei file trovati.

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/profile    |   A       |           |      |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc|           |    A      |      |
+----------------+-----------+-----------+------+
|~/.bashrc       |           |    B      |      |
+----------------+-----------+-----------+------+
|~/.bash_profile |   B1      |           |      |
+----------------+-----------+-----------+------+
|~/.bash_login   |   B2      |           |      |
+----------------+-----------+-----------+------+
|~/.profile      |   B3      |           |      |
+----------------+-----------+-----------+------+
|BASH_ENV        |           |           |  A   |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.bash_logout  |    C      |           |      |
+----------------+-----------+-----------+------+

Invece di pubblicare la stessa risposta su più domande, è preferibile poter personalizzare la risposta in base alle esigenze specifiche del richiedente. Se la risposta è esattamente la stessa per entrambe le domande, dovresti pubblicare una sola risposta e votare per chiudere le altre domande come duplicati dell'originale.
Mokubai

1
@Mokubai L'altra domanda è già stata contrassegnata come duplicata di questa.
Flimm,

@ElipticalView: dal set di non fare nulla, si sta facendo riferimento alla linea: [ -z "$PS1" ] && return? La tabella nella mia risposta sta fornendo l'elenco degli script eseguiti da Bash indipendentemente dal contenuto degli script, se lo script stesso ha la linea [ -z "$PS1" ] && return, ovviamente ciò avrebbe effetto, ma non penso che dovrebbe significare che dovrei cambiare il tavolo.
Flimm,

5

UN MEGLIO COMMENTO PER IL CAPO DI / ETC / PROFILE

Basandomi sulla grande risposta di Flimm sopra, ho inserito questo nuovo commento a capo del mio profilo Debian / etc / (potrebbe essere necessario modificarlo per la vostra distribuzione) :

# For BASH: Read down the appropriate column. Executes A, then B, then C, etc.
# The B1, B2, B3 means it executes only the first of those files found.  (A)
# or (B2) means it is normally sourced by (read by and included in) the
# primary file, in this case A or B2.
#
# +---------------------------------+-------+-----+------------+
# |                                 | Interactive | non-Inter. |
# +---------------------------------+-------+-----+------------+
# |                                 | login |    non-login     |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   ALL USERS:                    |       |     |            |
# +---------------------------------+-------+-----+------------+
# |BASH_ENV                         |       |     |     A      | not interactive or login
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile                     |   A   |     |            | set PATH & PS1, & call following:
# +---------------------------------+-------+-----+------------+
# |/etc/bash.bashrc                 |  (A)  |  A  |            | Better PS1 + command-not-found 
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/bash_completion.sh|  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/vte-2.91.sh       |  (A)  |     |            | Virt. Terminal Emulator
# |/etc/profile.d/vte.sh            |  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   A SPECIFIC USER:              |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_profile    (bash only)   |   B1  |     |            | (doesn't currently exist) 
# +---------------------------------+-------+-----+------------+
# |~/.bash_login      (bash only)   |   B2  |     |            | (didn't exist) **
# +---------------------------------+-------+-----+------------+
# |~/.profile         (all shells)  |   B3  |     |            | (doesn't currently exist)
# +---------------------------------+-------+-----+------------+
# |~/.bashrc          (bash only)   |  (B2) |  B  |            | colorizes bash: su=red, other_users=green
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_logout                   |    C  |     |            |
# +---------------------------------+-------+-----+------------+
#
# ** (sources !/.bashrc to colorize login, for when booting into non-gui)

E questa nota alla testa di ciascuno degli altri file di installazione per fare riferimento ad esso:

# TIP: SEE TABLE in /etc/profile of BASH SETUP FILES AND THEIR LOAD SEQUENCE

Vale la pena notare che penso che il profilo / etc / di Debian sia di default (include) /etc/bash.bashrc (quando esiste /etc/bash.bashrc). Quindi gli script di login leggono entrambi i file / etc, mentre il non-login legge solo bash.bashrc.

Da notare anche che /etc/bash.bashrc è impostato per non fare nulla quando non viene eseguito in modo interattivo. Quindi questi due file sono solo per script interattivi.


4

La logica di configurazione di Bash non è follemente complicata e spiegata in altre risposte in questa pagina, su serverfault e in molti blog. Il problema tuttavia è ciò che le distribuzioni Linux fanno di bash , intendo i modi complessi e vari che configurano bash di default. http://mywiki.wooledge.org/DotFiles menziona brevemente alcune di queste stranezze. Ecco una traccia di esempio su Fedora 29, che mostra quali file originano quali altri file e in quale ordine per uno scenario molto semplice: connettersi in remoto con ssh e quindi avviare un'altra sottoshell:

ssh fedora29
 └─ -bash # login shell
      ├── /etc/profile
      |    ├─ /etc/profile.d/*.sh
      |    ├─ /etc/profile.d/sh.local
      |    └─ /etc/bashrc
      ├── ~/.bash_profile
      |    └─ ~/.bashrc
      |          └─ /etc/bashrc
      |
      |
      └─ $ bash  # non-login shell
            └─ ~/.bashrc
                 └─ /etc/bashrc
                       └─ /etc/profile.d/*.sh

La logica più complessa di Fedora è in /etc/bashrc. Come visto sopra /etc/bashrcè un file bash di cui non è a conoscenza, intendo non direttamente. I /etc/bashrctest di Fedora se:

  • viene fornito da una shell di accesso,
  • viene fornito da una shell interattiva,
  • è già stato acquistato

... e poi fa cose completamente diverse a seconda di quelle.

Se pensi di ricordare il grafico sopra, allora è un peccato perché non è quasi sufficiente: questo grafico descrive semplicemente uno scenario, cose leggermente diverse quando si eseguono script non interattivi o si avvia una sessione grafica. Ho omesso ~/.profile. Ho omesso gli bash_completionscript. Per motivi di compatibilità con le versioni precedenti, invocare bash come /bin/shinvece di /bin/bashmodificarne il comportamento. Che dire di zsh e di altre shell? E, naturalmente, diverse distribuzioni Linux fanno le cose diversamente, per esempio Debian e Ubuntu hanno una versione non standard di bas h, ha personalizzazioni specifiche di Debian. Cerca in particolare un file insolito:/etc/bash.bashrc. Anche se ti attieni a una singola distribuzione Linux, probabilmente si evolve nel tempo. Aspetta: non abbiamo nemmeno toccato macOS, FreeBSD, ... Infine, pensiamo agli utenti bloccati con i modi ancora più creativi in ​​cui i loro amministratori hanno configurato il sistema che devono usare.

Come dimostra il flusso infinito di discussioni su questo argomento, è una causa persa. Finché vuoi solo aggiungere nuovi valori, alcuni "tentativi ed errori" tendono ad essere sufficienti. Il vero divertimento inizia quando si desidera modificare in un file (utente) qualcosa già definito in un altro (in / etc). Quindi preparati a dedicare del tempo a progettare una soluzione che non sarà mai portatile.

Per un ultimo divertimento ecco il "grafico sorgente" per lo stesso semplice scenario su Clear Linux a giugno 2019:

ssh clearlinux
 └─ -bash # login shell
      ├── /usr/share/defaults/etc/profile
      |    ├─ /usr/share/defaults/etc/profile.d/*
      |    ├─ /etc/profile.d/*
      |    └─ /etc/profile
      ├── ~/.bash_profile
      |
      |
      └─  $ bash   # non-login shell
           ├─ /usr/share/defaults/etc/bash.bashrc
           |      ├─ /usr/share/defaults/etc/profile
           |      |    ├─ /usr/share/defaults/etc/profile.d/*
           |      |    ├─ /etc/profile.d/*
           |      |    └─ /etc/profile
           |      └─ /etc/profile
           └─ ~/.bashrc
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.