Che cos'è esattamente una variabile d'ambiente?


42

So che VARIABLE=valuecrea una variabile di ambiente e la export VARIABLE=valuerende disponibile per i processi creati dalla shell corrente. envmostra le variabili di ambiente correnti, ma dove vivono? Cosa comprende una variabile d'ambiente (o un ambiente , per quella materia)?

Risposte:


29

Un ambiente non è magico come potrebbe sembrare. La shell lo memorizza e passa alla execve()chiamata di sistema. Il processo figlio lo eredita come un puntatore a matrice chiamato environ. Dalla execvemanpage:

SINOSSI

   #include <unistd.h>

   int execve(const char *filename, char *const argv[],
              char *const envp[]);

argvè una matrice di stringhe di argomenti passate al nuovo programma.
Per convenzione, la prima di queste stringhe dovrebbe contenere il nome file associato al file in esecuzione. envpè un array di stringhe, convenzionalmente in forma chiave = valore, che vengono passate come ambiente al nuovo programma.

La environ(7)manpage offre anche alcune informazioni:

SINOSSI

   extern char **environ;

DESCRIZIONE

La variabile environpunta a un array di puntatori a stringhe chiamato "ambiente". L'ultimo puntatore in questo array ha il valore NULL. (Questa variabile deve essere dichiarata nel programma utente, ma è dichiarata nel file di intestazione <unistd.h>nel caso in cui i file di intestazione provenissero da libc4 o libc5 e nel caso in cui provenissero da glibc e _GNU_SOURCE fosse definito.) Questo array di stringhe è reso disponibile a il processo dalla chiamata exec (3) che ha avviato il processo.

Entrambe queste manpage GNU corrispondono alla specifica POSIX


4
+1 vale probabilmente la pena notare che alcuni membri della exec(3)famiglia (cioè quelli che non corrispondono a exec * v) passano ** environment sotto le coperte.
msw,

5
Si noti che non si tratta di processi figlio (i processi figlio ereditano tutta la memoria del loro genitore), ma programmi eseguiti (nello stesso processo), quindi è un altro modo per passare i dati attraverso una chiamata di sistema execve () (che altrimenti cancella la memoria del processo).
Stéphane Chazelas,

@msw: sono le exec*evarianti che passano esplicitamente un env, invece di usare implicitamente la environvariabile globale. Il vsignificato di "vettore", e si riferisce agli argomenti della riga di comando passati come un array (piuttosto che un "elenco" (funzione di lunghezza variabile)) execveè una chiamata di sistema, e tutte le altre exec*funzioni sono wrapper libc per questo.
Peter Cordes,

19

Hai sbagliato un po ': SOME_NAME=valuecrea una variabile di shell (nella maggior parte delle shell). export SOME_NAME=valuecrea una variabile d'ambiente. Nel bene e nel male, la maggior parte delle shell Unix / Linux / * BSD usa una sintassi identica per accedere alle variabili di ambiente e alle variabili di shell.

In un senso più ampio, un "ambiente" è solo l'informazione che accompagna l'esecuzione del programma. Nei programmi C, si potrebbe trovare l'ID del processo con una getpid()chiamata, in un programma di shell si usa un accesso variabili: $$. L'ID processo è solo una parte dell'ambiente del programma. Credo che il termine "ambiente" derivi da alcuni dei più teorici argomenti di informatica, come la modellizzazione dell'esecuzione del programma. I modelli di esecuzione del programma hanno un ambiente "che contiene le associazioni tra variabili e i loro valori".

E quest'ultima, più forte definizione è ciò che un "ambiente" è per le shell Unix / Linux / * BSD: un'associazione tra nomi ("variabili") e i loro valori. Per la maggior parte delle shell in stile Unix, i valori sono tutte stringhe di caratteri, anche se non è così vero come una volta. Ksh, Zsh e Bash hanno tutti digitato variabili in questi giorni. È possibile esportare anche le definizioni delle funzioni della shell.

L'uso di un ambiente separato dalle normali variabili della shell implica il fork/execmetodo di avvio di un nuovo processo utilizzato da tutti gli Unix. Quando si è exportuna coppia nome / valore, quella coppia nome / valore sarà presente nell'ambiente dei nuovi eseguibili, avviata dalla shell con una execve(2)chiamata di sistema (in genere a seguito di a fork(2), tranne quando è execstato utilizzato il comando shell).

A seguito di execve(), la main()funzione del nuovo binario ha i suoi argomenti della riga di comando, l'ambiente (memorizzato come una matrice di puntatori alle var=valuestringhe terminata con NULL , vedere la environ(7)pagina man). L'altro stato ereditato include le ulimitimpostazioni, la directory di lavoro corrente e tutti i descrittori di file aperti per i quali il execve()chiamante non aveva FD_CLOEXEC impostato. Lo stato corrente di tty (eco abilitato, modalità raw, ecc.) Potrebbe anche essere considerato parte dello stato di esecuzione ereditato da un nuovo execprocesso.

Vedere la bashdescrizione del manuale dell'ambiente di esecuzione per comandi semplici (diversi dalle funzioni incorporate o shell).

L'ambiente Unix è diverso da almeno alcuni altri sistemi operativi: i "lessici" di VMS potrebbero essere modificati da un processo figlio e tale modifica era visibile nel genitore. Un VMS cdin un processo figlio influirebbe sulla directory di lavoro del genitore. Almeno in alcune circostanze, e la mia memoria potrebbe non riuscire a salvarmi.

Alcune variabili d'ambiente sono ben noti, $HOME, $PATH, $LD_LIBRARY_PATHe altri. Alcuni sono convenzionali con un determinato sistema di programmazione, quindi una shell genitore può trasmettere molte e molte informazioni speciali ad alcuni programmi, come una specifica directory temporanea, o un ID utente e una password che non compaiono in ps -ef. I semplici programmi CGI ereditano molte informazioni dal server Web tramite variabili di ambiente, ad esempio.


1
Sembrerebbe essere ancora un po 'più complicato. In bash almeno SOME_NAME=value commandimposterà la variabile d'ambiente SOME_NAME per quel richiamo del comando. Confusamente, non sembra impostare la variabile shell con lo stesso nome.
Samuel Edwin Ward,

2
Per essere più precisi, le variabili di ambiente non vengono ereditate ma passano piuttosto esplicitamente da una shell ai programmi generati.
msw,

2
@SamuelEdwinWard il motivo per cui ti SOME_NAME=value commandcomporti in contrasto con le tue aspettative è che si tratta di una sintassi speciale che significa "aggiungi SOME_NAME all'ambiente passato al comando ma non alterare altrimenti le variabili di questa shell".
msw,

1
Affascinante, il collegamento al calcolo lambda / programmazione funzionale. Questa è una connessione interessante che ha molto senso.
Matt,

1
Alcuni di questi non sono del tutto giusti. Ad esempio, sottoshell sono sottoprocessi e devono essere fork()Ed, ma fare ricevono (copie di variabili di shell).
Ruakh,

7

Le variabili d'ambiente nella loro forma più grezza sono solo un insieme di coppie nome / valore. Come descritto nella pagina man di bash ( man 1 bash) nella sezione AMBIENTE:

   When  a  program  is invoked it is given an array of strings called the
   environment.   This  is  a  list  of  name-value  pairs,  of  the  form
   name=value.

   The  shell  provides  several  ways  to manipulate the environment.  On
   invocation, the shell scans its own environment and creates a parameter
   for  each name found, automatically marking it for export to child pro-
   cesses.  Executed commands inherit the  environment.

In termini pratici, consente di definire un comportamento condiviso o unico per i programmi richiamati dalla presente shell. Ad esempio, quando si utilizza crontabo visudoè possibile definire la EDITORvariabile di ambiente per definire un altro editor diverso da quello utilizzato dal sistema per impostazione predefinita. Lo stesso può valere per cose come il mancomando che controlla il tuo PAGERambiente per capire con quale programma cercapersone usare il display per visualizzare l'output della pagina man.

Molti comandi unix leggono l'ambiente e, a seconda di ciò che è impostato, modificano il loro output / elaborazione / azione a seconda di questi. Alcuni sono condivisi, altri sono unici per il programma. La maggior parte delle pagine man contengono informazioni su come la variabile d'ambiente abbia un effetto sul programma descritto.

Altre illustrazioni pratiche riguardano cose come i sistemi con diverse installazioni di Oracle sulla stessa piattaforma. Impostando ORACLE_HOME, l'intera suite di comandi di Oracle (caricata dalla PATHvariabile di ambiente) quindi estrae impostazioni, definizioni, mappature e librerie da quella directory di livello superiore. Lo stesso vale per altri programmi come Java con la sua JAVA_HOMEvariabile di ambiente.

bash stesso ha molte variabili d'ambiente che possono cambiare il comportamento di una serie di cose da storia ( HISTSIZE, HISTFILEecc), dimensione schermo ( COLUMNS), completamento scheda ( FIGNORE, GLOBIGNORE) codifica / decodifica locale e carattere ( LANG, LC_*), prompt ( PS1.. PS4), e così via (cerca nuovamente la conoscenza dalla pagina man di bash).

Inoltre è possibile scrivere script / programmi che utilizzano le proprie variabili di ambiente personalizzate (per passare le impostazioni o modificare la funzionalità).


0

Le "variabili di ambiente" sono un insieme di valori con nome dinamico che possono influire sul comportamento dei processi in esecuzione su un computer.

Fanno parte dell'ambiente operativo in cui viene eseguito un processo. Ad esempio, un processo in esecuzione può eseguire una query sul valore della variabile di ambiente TEMP per individuare un percorso adatto per l'archiviazione dei file temporanei o la variabile HOME o USERPROFILE per trovare la struttura di directory di proprietà dell'utente che esegue il processo.

Maggiori informazioni qui → http://en.wikipedia.org/wiki/Environment_variable .

Tutto quello che vuoi sapere sulle variabili d'ambiente ... ↑


1
Sebbene sia improbabile che questo collegamento scompaia, è meglio rispondere alla domanda qui con un testo pertinente e fornire il collegamento come aggiunta per le informazioni di backup.
Anthon,

@Anthon Credo che tu abbia ragione e farò le modifiche appena posso ... Grazie per il consiglio ...
SoCalDiegoRob,

-1

Questa risposta richiede una certa esperienza e conoscenza di scripting della shell con i termini variabile, valore, sostituzione variabile, prompt, eco, kernel, shell, utility, sessione e processo.

Una variabile d'ambiente (envar) è un insieme di variabili globali definite che possono influenzare il modo in cui un determinato processo si comporterà sul sistema operativo di un computer.

1. Un'introduzione esemplare:

Sostituiamo gli inviati con una $e lettere maiuscole . Ad esempio: $PS1.

Possiamo stampare un envar in questo modo:

echo $PS1

$PS1contiene il valore del prompt Unix. Supponiamo che siano i suoi valori nativi \u \w $.

  • \u sta per (attuale) utente,
  • \w sta per directory di lavoro,
  • $ è delimitare il prompt.

Quindi, se lo facciamo: echo $PS1vediamo i valori di \u, \wpiù il simbolo del dollaro alla fine.

Potremmo cambiare il comportamento di Unix in quel contesto, se cambiassimo i valori di quella envar. Per esempio:

PS1="\w >"

Ora il prompt è simile al seguente (supponendo che la directory di lavoro sia denominata "John"):

John >

Allo stesso modo in cui potremmo fare PS1="Hello, I'm your prompt >", quindi echo $PS1porteremo:

Hello, I'm your prompt >

In Bash 4.xx, possiamo stampare TUTTI gli envars nel sistema con il envcomando. Suggerisco di eseguire envnel terminale e dare un'occhiata all'output.

2. Come vengono mostrati e manipolati questi dati:

Il terminale di una sessione ci consente di personalizzare i dintorni che stanno arrivando con Bash.

Le modifiche sopra menzionate sono generalmente temporanee, ed ecco perché:

Ogni sessione (che non è una sotto-sessione) è unica e diversi processi possono essere eseguiti in modo univoco allo stesso tempo (ognuno con il proprio set di envars) ma di solito c'è ereditarietà dalla sessione 0 alla sessione 1 e successive.

Le modifiche apportate a un processo sono uniche per esso e cesseranno se la chiudiamo senza salvarle in alcun modo.

Quindi, come possiamo salvare queste modifiche:

Esistono diversi tipi di modi disponibili per memorizzare le modifiche envar, a seconda dell'ambito scelto. Ecco diversi ambiti (livelli) per tali modifiche:

  • Livello di processo: i dintorni sono disponibili solo per i programmi nella sessione corrente.
  • Livello di esportazione: i dintorni sono disponibili per i programmi nella sessione corrente o in tutte le sue sessioni secondarie.
  • Livello globale: le modifiche verranno archiviate per tutte le sessioni (primaria e secondaria).

Dove sono archiviati i dati envar:

Unix è composto da 3 livelli principali: kernel, shell e utility. AFAIK ogni shell ha i suoi dintorni, e questi sono costruiti principalmente o esclusivamente nella shell.

La posizione specifica in cui cambiarli a livello globale è di solito /etc/profilesebbene possiamo anche farlo .bashrcovviamente.

3. Creazione di nuovi ambienti:

Possiamo creare nuovi ambienti ed ecco un modo; a partire da Bash 4.xx non esiste un enavar nativo chiamato MESSAGE(come detto, gli envar sono generalmente maiuscoli).

MESSAGE="Hello world!"

lo creeremo per noi, e ora se digitiamo echo $MESSAGE, otteniamo hello world!.

Se eseguiremo bashnella nostra sessione di lavoro corrente (finestra), inizieremmo una nuova sottosessione bash e non funzioneremo più nel processo originale, a meno che non eseguiamo exit.

Nota: nei sistemi operativi con un emulatore di terminale (come il desktop Ubuntu), una sottosessione di solito viene eseguita sulla stessa finestra, ma una nuova sessione in un'altra finestra non è una sottosessione di quella esistente (è un processo adiacente ) .

Nota: non usare segni speciali nei valori envar come! o non saranno salvati.

Esportazione di envar dalla sessione originale a tutte le sessioni secondarie:

Possiamo ancora usare l'envar creato nella prima sessione, anche nella seconda, senza registrarlo nei file di configurazione dell'utente o globale (vedere i dati seguenti). Ecco come farlo:

Vai alla sessione originale (nella finestra corrente o in un'altra) ed esegui:

export MESSAGE

durante l'esportazione, non utilizzare un $segno.

Ora viene esportato in tutte le sessioni secondarie. Se lo farai echo $MESSAGEin una sottosessione, sia dal tuo utente che da un altro, verrà stampato.

Si noti che le variabili interne di Shell come PS1non dovrebbero essere esportate, ma se si desidera esportarle da qualsiasi motivo e non vengano visualizzate, non eseguire bashdopo export, ma piuttosto bash –norc.

4. Il $ PATH envar:

$PATH è l'invar che gli utenti cambieranno di solito di più.

Se noi echo $PATH, vedremo questo stream:

/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

I valori stampati di questo envar sono separati da due punti (:) lì, ma ecco un modo potenzialmente più comodo (questi sono gli stessi valori):

/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

Queste sono directory da cercare, quando eseguiamo un'utilità.

Eseguendo which echootterremo la posizione del suo file - per esempio, potremmo vedere che esiste /bin/echo.

Sulla base di ciò non è necessario digitare echo envar per visualizzare i valori di evnar. Possiamo anche fare:

/bin/echo $ENVAR

Envar verrà comunque eseguito, ad esempio:

/bin/echo $HOME

Ci da

/home/User || /root

Proprio come:

echo $HOME

Ci da

/home/User || /root

Nota: $HOMEè abbreviato come ~.

Il sistema: relazioni $ PATH e una possibile interazione dell'utente:

In Bash 4.xx, quando utilizziamo un'utilità senza il suo percorso completo, il sistema utilizzerà tutti e 6 i valori sopra menzionati, di $PATHenvar. Quindi, inizierà da /user/local/bine seguirà tutto il suo contenuto alla ricerca echodell'eseguibile.

In questo caso, si fermerà a /bin/echo, in cui, in questo caso, risiede l'eseguibile.

Quindi, il motivo principale per cui potremmo personalizzare $PATHenvar, è l'installazione di file eseguibili che non rientrano in nessuno dei suoi valori nativi.

Dopo aver installato tali eseguibili, dovremmo impostare il loro $PATHvalore di conseguenza e quindi saremmo in grado di lavorare con loro.

5. Appendice - espansione $PATH:

Possiamo export $PATHbash sub-sessioni (che include estensioni bash come WP-CLI per WordPress o Drush per Drupal) in questo modo:

export PATH="/home/John:$PATH"

Ciò aggiungerà un nuovo valore /home/Johna $PATH, e poi subito dopo, annetterà tutti i valori nativi (subito dopo i due punti), che sono memorizzati nella sintassi $PATH.

Tale modifica permanente può essere effettuata nello script pertinente, di solito sotto /etc/profilee con il nome .bashrc.


3
C'è molto di sbagliato in questa risposta: conflazione di sessioni e processi, avvertimento !in un valore della variabile d'ambiente non funzionante che è proprio sotto un esempio che mostra che funziona, una falsa nozione di sotto-sessioni, consigli piuttosto bizzarri su cosa fare dopo aver esportato una variabile di shell e una falsa nozione di variabili di ambiente globali.
JdeBP

warning about ! in an environment variable value not working that is right below an example showing it working? Per favore esempio.
JohnDoea,

quite bizarre advice about what to do after exporting a shell variable, cosa intendi esattamente?
JohnDoea,

false notion of global environment variables, cosa intendi esattamente?
JohnDoea,
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.