Risposte:
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 execve
manpage:
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
environ
punta a un array di puntatori a stringhe chiamato "ambiente". L'ultimo puntatore in questo array ha il valoreNULL
. (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
exec*e
varianti che passano esplicitamente un env, invece di usare implicitamente la environ
variabile globale. Il v
significato 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.
Hai sbagliato un po ': SOME_NAME=value
crea una variabile di shell (nella maggior parte delle shell). export SOME_NAME=value
crea 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/exec
metodo di avvio di un nuovo processo utilizzato da tutti gli Unix. Quando si è export
una 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 è exec
stato 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=value
stringhe terminata con NULL , vedere la environ(7)
pagina man). L'altro stato ereditato include le ulimit
impostazioni, 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 exec
processo.
Vedere la bash
descrizione 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 cd
in 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_PATH
e 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.
SOME_NAME=value command
imposterà la variabile d'ambiente SOME_NAME per quel richiamo del comando. Confusamente, non sembra impostare la variabile shell con lo stesso nome.
SOME_NAME=value command
comporti 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".
fork()
Ed, ma fare ricevono (copie di variabili di shell).
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 crontab
o visudo
è possibile definire la EDITOR
variabile di ambiente per definire un altro editor diverso da quello utilizzato dal sistema per impostazione predefinita. Lo stesso può valere per cose come il man
comando che controlla il tuo PAGER
ambiente 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 PATH
variabile 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_HOME
variabile di ambiente.
bash stesso ha molte variabili d'ambiente che possono cambiare il comportamento di una serie di cose da storia ( HISTSIZE
, HISTFILE
ecc), 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à).
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 ... ↑
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.
Sostituiamo gli inviati con una $
e lettere maiuscole . Ad esempio: $PS1
.
Possiamo stampare un envar in questo modo:
echo $PS1
$PS1
contiene 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 $PS1
vediamo i valori di \u
, \w
più 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 $PS1
porteremo:
Hello, I'm your prompt >
In Bash 4.xx, possiamo stampare TUTTI gli envars nel sistema con il env
comando. Suggerisco di eseguire env
nel terminale e dare un'occhiata all'output.
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.
Esistono diversi tipi di modi disponibili per memorizzare le modifiche envar, a seconda dell'ambito scelto. Ecco diversi ambiti (livelli) per tali modifiche:
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/profile
sebbene possiamo anche farlo .bashrc
ovviamente.
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 bash
nella 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.
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 $MESSAGE
in una sottosessione, sia dal tuo utente che da un altro, verrà stampato.
Si noti che le variabili interne di Shell come PS1
non dovrebbero essere esportate, ma se si desidera esportarle da qualsiasi motivo e non vengano visualizzate, non eseguire bash
dopo export
, ma piuttosto bash –norc
.
$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 echo
otterremo 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 ~
.
In Bash 4.xx, quando utilizziamo un'utilità senza il suo percorso completo, il sistema utilizzerà tutti e 6 i valori sopra menzionati, di $PATH
envar. Quindi, inizierà da /user/local/bin
e seguirà tutto il suo contenuto alla ricerca echo
dell'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 $PATH
envar, è l'installazione di file eseguibili che non rientrano in nessuno dei suoi valori nativi.
Dopo aver installato tali eseguibili, dovremmo impostare il loro $PATH
valore di conseguenza e quindi saremmo in grado di lavorare con loro.
$PATH
:Possiamo export $PATH
bash 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/John
a $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/profile
e con il nome .bashrc
.
!
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.
warning about ! in an environment variable value not working that is right below an example showing it working
? Per favore esempio.
quite bizarre advice about what to do after exporting a shell variable
, cosa intendi esattamente?
false notion of global environment variables
, cosa intendi esattamente?
exec(3)
famiglia (cioè quelli che non corrispondono a exec * v) passano ** environment sotto le coperte.