Qual è il modo migliore di distro / shell-agnostico per impostare le variabili di ambiente?


31

La domanda dice tutto. Attualmente uso Arch Linux e zsh, ma mi piacerebbe una soluzione che (almeno) funziona sia su VT che su xterms e anche (si spera, preferibilmente) continuerà a funzionare se cambio distro o shell.

Ho sentito risposte selvaggiamente disparate a questa domanda in diversi documenti di distro. Ubuntu dice "usa .pam_environment". Penso che in Arch ciò che raccomandano dipende dalla tua shell. Attualmente inserisco tutto in .profile e se una shell non lo fornisce per qualche motivo (es. Bash se esiste .bash_profile), lo sovrascrivo acquistandolo manualmente. Ma sembra che ci debba essere un modo migliore.


2
Questo non ha nulla a che fare con la distro e tutto con la shell. Non sono sicuro che ci sia un modo portatile per farlo, però.
Joseph R.,

Hmm. Impressionante .
strugee,

Risposte:


29

Purtroppo non esiste una posizione completamente portatile per impostare le variabili di ambiente. I due file che si avvicinano sono ~/.profile: la posizione tradizionale e pronta all'uso su molte configurazioni e ~/.pam_environment, un'alternativa moderna, banale ma limitata.

Cosa mettere ~/.pam_environment

Il file ~/.pam_environmentviene letto da tutti i metodi di accesso che utilizzano PAM e che hanno questo file abilitato. Questo copre la maggior parte dei sistemi Linux al giorno d'oggi.

Il vantaggio principale ~/.pam_environmentè che (quando abilitato) viene letto prima dell'avvio della shell dell'utente, quindi funziona indipendentemente dal tipo di sessione, dalla shell di accesso e da altre complessità. Funziona anche con accessi non interattivi come su -c somecommande ssh somecommand.

Il limite principale di ~/.pam_environmentè che puoi solo inserire compiti semplici lì, non sintassi complessa della shell. La sintassi di questo file è la seguente.

  • I file vengono analizzati riga per riga.
  • Lo spazio bianco principale viene ignorato.
  • Puoi facoltativamente iniziare le linee con exporte un singolo spazio (non una scheda, vai a figura).
  • Successivamente, ogni riga deve avere la forma in VAR=VALUEcui VAR è composto da lettere, cifre e caratteri di sottolineatura.
  • # inizia un commento, non può apparire in un valore.
  • Se VALUE inizia con 'o "e contiene un'altra virgoletta identica, VAR viene impostato sulla stringa tra virgolette (tutto ciò che segue la seconda virgoletta viene ignorato). Altrimenti VAR è impostato sulla stringa dopo il =segno.
  • In caso contrario =, la variabile viene rimossa dall'ambiente.

Quindi, al rialzo, ~/.pam_environmentfunziona in una vasta gamma di circostanze. Sul lato negativo, non è possibile avere impostazioni dinamiche come basare il valore di una variabile su un'altra variabile (ad esempio aggiungendo una directory a PATH) o usare l'output di un comando (ad esempio test se è presente una directory o un programma), e alcuni i caratteri ( #'", newline) sono impossibili o problematici da inserire nel valore.

Cosa mettere ~/.profile

Questo file dovrebbe avere una sintassi sh portatile (POSIX). Usa le estensioni ksh o bash (array, [[ … ]]ecc.) Solo se sai che il tuo sistema ha queste shell come /bin/sh.

Questo file può essere letto da script in applicazioni automatizzate, quindi non deve chiamare programmi che producono output o chiamate exec. Se vuoi farlo sugli accessi in modalità testo, fallo solo per shell interattive. Esempio:

case $- in *i*)
  # Display a message if I have new mail
  if mail -e; then echo 'You have new mail'; fi
  # If zsh is available, and this looks like a text-mode login, run zsh
  case "`ps $PPID` " in
    *" login "*)
      if type zsh >/dev/null 2>/dev/null; then exec zsh; fi;;
  esac
esac

Questo è un esempio dell'uso /bin/shdella shell di login e del passaggio alla shell preferita. Vedi anche come posso usare bash come shell di login quando il mio amministratore di sistema rifiuta di farmi cambiare

Quando ~/.profilenon viene letto su login non grafico?

Diverse shell di login leggono file diversi.

Se la shell di accesso è bash

Bash legge ~/.bash_logino ~/.bash_profilese esistono invece di ~/.profile. Inoltre bash non legge ~/.bashrcin una shell di login anche se è interattiva. Per non dover più ricordare queste stranezze, crea un ~/.bash_profilecon le seguenti due righe:

. ~/.profile
case $- in *i*) . ~/.bashrc;; esac

Vedi anche Quali file di installazione dovrebbero essere usati per impostare le variabili d'ambiente con bash?

Se la shell di accesso è zsh

Zsh legge ~/.zprofilee ~/.zlogin, ma non ~/.profile. Zsh ha una sintassi diversa da sh, ma può leggere ~/.profilein modalità di emulazione sh. Puoi usarlo per il tuo ~/.zprofile:

emulate sh -c '. ~/.profile'

Vedi anche Zsh che non colpisce ~ / .profile

Se la shell di accesso è un'altra shell

Non c'è molto che puoi fare lì, a meno di usarlo /bin/shcome shell di accesso e la tua shell preferita (come il pesce) solo come shell interattiva. Questo è quello che faccio con zsh. Vedi sopra per un esempio di invocazione di un'altra shell da ~/.profile.

Comandi remoti

Quando si richiama un comando remoto senza passare attraverso una shell interattiva, non tutte le shell leggono un file di avvio.

Ksh legge il file specificato dalla ENVvariabile, se riesci a passarlo.

Bash legge ~/.bashrcse non è interattivo (!) E il suo processo genitore viene chiamato rshdo sshd. Quindi puoi iniziare ~/.bashrccon

if [[ $- != *i* ]]; then
  . ~/.profile
  return
fi

Zsh legge sempre ~/.zshenvquando inizia. Usare con cautela, poiché questo viene letto da ogni singola istanza di zsh, anche quando si tratta di una subshell in cui sono state impostate altre variabili. Se zsh è la tua shell di login e vuoi usarla per impostare le variabili solo per i comandi remoti, usa un guard: imposta qualche variabile in ~/.profile, come MY_ENVIRONMENT_HAS_BEEN_SET=yes, e controlla questo guard prima di leggere ~/.profile.

if [[ -z $MY_ENVIRONMENT_HAS_BEEN_SET ]]; then emulate sh -c '~/.profile'; fi

Il caso degli accessi grafici

Molte distribuzioni, gestori di display e ambienti desktop si organizzano per l'esecuzione ~/.profile, sia approvvigionandolo esplicitamente dagli script di avvio o eseguendo una shell di accesso.

Sfortunatamente, non esiste un metodo generale per gestire combinazioni distro / DM / DE dove ~/.profilenon viene letto.

Se si utilizza una sessione tradizionale avviata da ~/.xsession, questo è il luogo in cui è necessario impostare le variabili di ambiente; farlo acquistando ~/.profile(cioè . ~/.profile). Si noti che in alcune configurazioni, gli script di avvio dell'ambiente desktop verranno ~/.profilenuovamente generati .


ciò che case $- in *i*)fare?
qodeninja,

2
@qodeninja Esegue le seguenti istruzioni (fino alla corrispondenza ;;o esac) se $-corrisponde al modello *i*, ovvero se $-contiene i, ovvero se la shell è interattiva.
Gilles 'SO- smetti di essere malvagio' il

$-è una stringa delle opzioni di shell attualmente impostate. (come set -x). isignifica shell interattiva.
Peter Cordes,

Non puoi semplicemente creare un file comune, per esempio ~/.config/env, anche senza emulazione?
Kevin Suttle,

1
@ StéphaneChazelas Questa è una visione purista. Mantengo la mia .profileconformità con le conchiglie Bourne piuttosto vecchie, ma riconosco che ad alcune persone non importa. Non ho nulla contro le persone che suppongono che sh = bash per i propri file, mi interessa solo se pubblicano #!/bin/shscript che usano le funzionalità bash.
Gilles 'SO- smetti di essere malvagio' il

4

Per quanto ne so non esiste uno standard agnostico di distro e shell su come impostare le variabili di ambiente.

Lo standard più comune e di fatto sembra essere /etc/profilee ~/.profile. Il secondo più comune sembra essere /etc/environmente ~/.pam_environment.

Mi sembra che tutta la documentazione che ti ho trovato abbia già trovato. Li elenco qui comunque per gli altri lettori.

  • Debian raccomanda /etc/profilee ~/.profile( link ).
  • Ubuntu consiglia /etc/environmente ~/.pam_environment( link ).
  • Arch Linux menziona, tra gli altri, /etc/profilee /etc/environment( link ).

Bonus: un testo che mette in discussione l'uso e / o l'abuso di /etc/environmentin debian ( link , ultimo aggiornamento 2008).


Indipendentemente dal file che usi, ti imbatteresti comunque in una sintassi incompatibile tra diverse shell.
Joseph R.,

1
@JosephR. la maggior parte delle shell non mantiene la retrocompatibilità con sh? Finché ti atterrai a POSIX, avrei pensato che saresti
andato

1
AFAIK non puoi assegnare variabili cshe amici nel modo POSIX (hai bisogno di qualcosa di simile seto setenv)
Joseph R.

0

Ho aggiunto il seguente script ~ / bin / agnostic_setenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]="
   exit 0
endif

if ($#args == 2) then
   if ("$args[1]" =~ *csh*) then 
      echo "setenv $args[2]"
      exit 0
   else
      echo "export $args[1]=$args[2]"
      exit 0
   endif
endif

echo "setenv $args[2] $args[3]"

E in ~ / .perl-homedir uso:

eval `${HOME}/bin/agnostic_setenv $shell PERL_HOMEDIR 0`

Uno script simile per agnostic_unsetenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]"
   exit 0
endif

echo "unsetenv $args[2]"
exit 0
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.