Dove devo esportare una variabile d'ambiente in modo che tutte le combinazioni di bash / dash, interattivo / non interattivo, login / non login, la raccolgano?


11

Ecco la motivazione per la domanda:

Sto usando Ubuntu 12.04 LTS 2 con il desktop Unity. Nel mio file .bashrc, aggiungo diverse directory alla mia variabile PATH e definisco alcune variabili d'ambiente, come JAVA_HOME. Quando avvio applicazioni da un terminale (eseguendo bash, la mia shell predefinita), questo funziona alla grande, ma per molte delle scorciatoie che usano il launcher Unity, eseguono app che sembrano essere definite per usare #! / Bin / sh, che è alias / bin / dash e non raccolgono il contenuto di ~ / .bashrc o ~ / .profile.

Suppongo che potrei cambiare tutte queste scorciatoie per usare / bin / bash invece di / bin / sh per forzarlo a raccogliere le modifiche .bashrc, ma questo sembra davvero confuso.

Dato che Ubuntu 12.04 (di default) alias / bin / sh to / bin / dash e che la mia shell predefinita è / bin / bash, c'è un solo posto dove posso scegliere di modificare il PERCORSO e definire le variabili di ambiente se le voglio essere presente in tutte queste circostanze:

  1. Ogni volta che creo una shell bash senza login (usando il terminale in unità)
  2. Ogni volta che creo una shell bash di login (ad esempio, il login in remoto tramite ssh)
  3. Ogni volta che utilizzo un launcher dell'applicazione Unity (dato che il launcher usa / bin / sh).
  4. Ogni volta che viene eseguito un processo cron (dato che SHELL = / bin / sh in / etc / crontab).

Se capisco correttamente, suppongo che:

  • (1) / (2) e (3) / (4) sono diversi perché (1) / (2) sono bash e (3) / (4) sono trattini.
  • (1) e (2) sono diversi perché i file che bash sceglie di caricare differiscono a seconda che si tratti o meno di una shell di accesso.
  • (3) e (4) sono diversi perché (3) arriverà ad un certo punto dopo che ho effettuato l'accesso (e quindi ~ / .profile sarà stato fornito da uno dei suoi processi padre, mentre (4) arriverà in alcuni punto quando non ho effettuato l'accesso, quindi ~ / .profile non sarà stato letto.

(Non sarei sorpreso se anche altri fattori contano, come se la shell sia interattiva o meno, quindi probabilmente ci sono più combinazioni che non ho nemmeno previsto ... Sono felice di avere la mia domanda "migliorata " in quel caso.)

Mi aspetto che a un certo punto qualcuno debba aver fatto una sorta di guida che ti dice come / dove modificare le variabili di ambiente in modo indipendente dalla shell (o almeno un modo compatibile con dash / bash) ... Posso solo ' non sembra trovare i termini di ricerca giusti per individuare tale guida.

Soluzioni o suggerimenti per soluzioni molto apprezzate!

aggiornato:

  • Chiarimento: questo è l'utente Ubuntu predefinito creato dal processo di installazione 12.04, quindi niente di speciale. Si fa avere un ~ / .profile (che esplicitamente le fonti ~ / .bashrc), e l'unico ~ / .bash * file presenti sono .bashrc, .bash_history e .bash_logout ... quindi non c'è nessun .bash_profile.
  • Enfasi sull'ambito: non mi interessa davvero alcuna shell diversa dalla shell interattiva predefinita (bash) e qualsiasi script che utilizza / bin / sh (aliasato al trattino), quindi non è necessario complicarlo con qualcosa in più per tcsh / ksh / zsh / etc. supporto.

2
Inseriscilo in un file, quindi lascialo ad altri file rc.
konsolebox,

Secondo la dash man che ho qui dovrebbe leggere $ HOME / .profile per le shell di login.
Etan Reisner,

@konsolebox Quali file rc? AFAICT, dash non ha un file rc. E come ho detto, dash non sembra raccogliere il contenuto di ~ / .profile.

@EtanReisner Sì, e questo è il punto della domanda. Quando dash non è in esecuzione come shell di login (e quindi ~ / .profile non è di provenienza), e allora?

@Mickalot Corri in modo interattivo? In caso contrario, prova ad aggiungere l'opzione -l.
konsolebox,

Risposte:


9

L'invocazione della shell è un po 'complicata. Le pagine man bash e dash contengono INVOCATIONsezioni su questo.

In sintesi, dicono (ci sono più dettagli nella pagina man, dovresti leggerlo):

When bash is                   | it reads
-------------------------------|----------
login shell                    | /etc/profile and then the first of ~/.bash_profile, ~/.bash_login or ~/.profile that exists.
                               |
interactive non-login shell    | /etc/bash.bashrc then ~/.bashrc
                               |
non-interactive shell          | The contents of $BASH_ENV (if it exists)
                               |
interactive (as "sh")          | The contents of $ENV (if it exists)

-

When dash is                   | it reads
-------------------------------|---------
login shell                    | /etc/profile then .profile
                               |
interactive shell              | The contents of ENV (it it exists, can be set in .profile as well as in initial environment)

Non conosco le altre conchiglie perché non ne uso mai nessuna. La tua scommessa migliore potrebbe essere quella di impostare un paio di variabili d'ambiente in modo che puntino allo script di posizione comune e lo provino manualmente (quando appropriato) nei due casi che non coprono.


Purtroppo, il nocciolo di questo problema è quello che manca alla tua dashboard. Quando il desktop Unity invoca qualsiasi script che inizia con #! / Bin / sh, avvia (quello che presumo sia) una dash shell non di accesso, non interattiva. Quindi la domanda è: come faccio a fare le stesse variabili di ambiente disponibili ci che sono presenti ovunque nella matrice?

Destra. Immagino sia per questo che Bash ha aggiunto BASH_ENV per quello slot. Dato che il trattino non sembra avere nulla che funzioni in quello slot, non sono sicuro che tu possa risolvere quel problema senza influenzare il cambiamento nell'ambiente dell'applicazione che avvia il trattino (tale trattino lo eredita). Ciò richiederebbe l'impostazione delle variabili di ambiente nell'ambiente X in cui entra in gioco il commento .xsession (rc) di @Mickalot. Questo lascia ancora, come ha indicato, il quarto punto escluso (ma credo che sia in qualche modo intenzionale).
Etan Reisner,

Dato che sono su Ubuntu 12.04 LTS, cron è in realtà pixie-cron, quindi posso definire le variabili env nel mio file crontab ... Sto indovinando SHELL = / bin / bash e BASH_ENV = ~ / .bashrc dovrebbe farlo?

3

Quindi, ci sono diversi modi per affrontarlo. Molte persone:

un. Avere un file che ha cose in comune con tutte le tue shell sh-style, diciamo .shcommone in ciascuna delle .profile .bashrc .kshrcet cetra, procedi con questo. .shcommon

b. Metti tutto dentro .profilee procurati questo dagli altri file.

Le cose necessarie per shell specifiche o per shell interattive vs non interattive possono quindi andare nel file appropriato prima di approvvigionarsi .shcommon

Personalmente, non mi piace gestire più file. Quindi, utilizzo il seguente approccio:

Innanzitutto, tutto ciò di cui ho bisogno va dal .profile momento che ho alcune cose specifiche bash e ksh, determino l'attuale nome della shell usando quanto segue:

# get name of current shell
# strip leading - from login shell
export SHELLNAME="${0#-}"

e quindi avere comandi per shell specifiche in qualcosa di simile al seguente (alcuni preferirebbero un'istruzione case).

if [ "$SHELLNAME" = 'bash' ]
then
    shopt -s checkwinsize

elif [ "$SHELLNAME" = 'ksh' ]
then
    stty erase ^?
fi

Se ho comandi che dovrebbero essere eseguiti solo in shell interattive, utilizzo quanto segue:

# check for interactive flag i in shell options $-
# in bash and ksh you could use the following, but breaks in dash
# if [[ $- == *i* ]]
if [ "$(echo $- | grep i)" != "" ]
then
  fortune
fi

Le cose che sono comuni in tutte le shell sh-style, ad esempio, PATHpossono semplicemente andare in cima.

Quindi, utilizzo i collegamenti simbolici per caricare lo stesso file in tutte le shell sh-style:

ln -s .profile .bashrc
ln -s .profile .kshrc

Un paio di note a margine, se hai un .bash_profile, allora bash caricherà questo invece di .profilema dash e ksh continueranno a caricare .profile Questo potrebbe essere parte del tuo problema.

Inoltre, potresti prendere in considerazione l'utilizzo #!/bin/bashnei tuoi script anziché a #!/bin/dashmeno che tu non voglia davvero script compatibili con POSIX. bash ha molte funzionalità extra che sono molto belle e trattate con dash o bash poiché sh disabiliterà molte di queste funzionalità.

Inoltre, la pagina man di bash fa un buon lavoro nel spiegare quando viene caricato il .profileversus .bashrc. Regole simili si applicano a ksh. dash carica .profileall'accesso e consente di caricare un file all'avvio di shell interattive che viene specificato utilizzando la ENVvariabile d'ambiente in .profile(controllare anche la pagina man dash e cercare .profile).


Non potresti semplicemente testare $ 0 per il nome della shell? Ci sono shell / casi in cui ciò non funziona?
Etan Reisner,

Allo stesso modo, il controllo di i in $ - non è sufficiente per il test interattivo della shell? (Si innescherà su shell interattive senza un tty che concedo, ma potrebbe o meno essere un effetto collaterale indesiderato.)
Etan Reisner,

@Etan: Hrm, so che ho provato per la prima volta $0e ho riscontrato problemi ... Non riesco a ricordare esattamente cosa fossero. Accedere direttamente alla console viene visualizzato $0come -bashinvece di bashma che potrebbe essere risolto.

@Etan: Sì, anche il check-in $-dovrebbe funzionare. Dovrei pensare a quando avresti una shell interattiva senza un tty? La tua soluzione ha una "sensazione" migliore per qualche ragione, posso cambiarla.

La -in -bashmezzo "shell di login" ma sì si avrebbe bisogno di conto per che nei luoghi in cui si prova l'valore o da visualizzare a qualcuno.
Etan Reisner,

0

Poiché i casi (1) e (2) vengono risolti acquistando le mie variabili di ambiente in .bashrc e .profile, la vera domanda è "qual è il nome del file in cui ho origine queste stesse variabili per (3) e (4).

Sembra che ci sia una risposta alla parte (3) della domanda (come posso importare la variabile d'ambiente da importare nel desktop Unity) su askubuntu . Il suggerimento è di creare un file ~ / .xsessionrc che verrà fornito da / etc / X11 / Xsession. (L'ho provato, e sembra funzionare ... yay!)

Sono ancora perplesso su cosa fare per (4). Sicuramente, se io creo un job di cron (o daemon), posso sostituire '/ bin / foo' con qualcosa di simile 'bash -i -c / bin / foo' per forzarlo ad utilizzare bash per caricare le variabili di ambiente giuste, ma questo significa anche che dovrò armeggiare con eventuali strumenti di terze parti che potrebbero installare attività daemon o cron job per mio conto. Che schiffo.

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.