Éppen egy olyan problémába ütköztem, amely azt mutatja, hogy nem vagyok egyértelmű a shell változók hatókörében.
Próbáltam használja a bundle install
parancsot, amely egy Ruby parancs, amely az $GEM_HOME
értékét használja munkájának elvégzéséhez. A következőt állítottam be: $GEM_HOME
, de a parancs mindaddig figyelmen kívül hagyta ezt az értéket, amíg nem használtam a export
-t, mint a export GEM_HOME=/some/path
.
Olvastam, hogy ettől a változó valahogy “globális” lesz (más néven környezeti változó ), de nem teszem értsd meg, mit jelent ez. Tudok a globális programokról, de a különálló programokról nem.
Továbbá, mivel az ilyen változók beállítása csak az aktuális shell munkamenetre vonatkozik, hogyan állítanám be őket mondjuk egy démonizált folyamatra?
Milyen hatókörökkel rendelkezhetnek a shell változók?
Válasz
A folyamatok faként vannak szervezve: minden folyamatnak egyedi szülője van, kivéve a init
t, amely PID
mindig 1, és nincs szülője.
Az új folyamat létrehozása általában fork
/ execv
rendszerhívások, ahol a gyermekfolyamat környezete a szülői folyamat másolata .
Ahhoz, hogy egy változó bekerüljön a környezetbe a héjból, export
meg kell adnia azt a változót, hogy az rekurzív módon minden gyermek számára látható legyen. De ne feledje, hogy ha egy gyermek megváltoztatja egy változó értékét, akkor a megváltozott érték csak számára látható, és minden, a változás után után létrehozott folyamat (mint másolat , mint korábban
Vegye figyelembe azt is, hogy egy gyermek folyamat megváltoztathatja a környezetét, például visszaállíthatja az alapértelmezett értékekre, amint az valószínűleg a login
példa.
Megjegyzések
Válasz
At legkevesebb ksh
és bash
alatt a változók három hatókörök, nem kettő , mint az összes többi válasz.
Az exportált (azaz környezeti) változó és a héj nem exportált változó hatókörein kívül van egy harmadik szűkebb is a függvény lokális változók számára.
A shell funkciókban a typeset
token csak azokban a függvényekben látható, amelyekben deklarálva vannak, és onnan meghívott (al) függvényekben.
Ez ksh
/ bash
kód:
# Create a shell script named /tmp/show that displays the scoped variables values. echo "echo [$environment] [$shell] [$local]" > /tmp/show chmod +x /tmp/show # Function local variable declaration function f { typeset local=three echo "in function": . /tmp/show } # Global variable declaration export environment=one # Unexported (i.e. local) variable declaration shell=two # Call the function that creates a function local variable and # display all three variable values from inside the function f # Display the three values from outside the function echo "in shell": . /tmp/show # Display the same values from a subshell echo "in subshell": /tmp/show # Display the same values from a disconnected shell (simulated here by a clean environment start) echo "in other shell" env -i /tmp/show
létrehozza ezt a kimenetet:
in function: [one] [two] [three] in shell: [one] [two] [] in subshell: [one] [] [] in other shell [] [] []
Amint láthatja, az exportált változó az első három helyről jelenik meg, az exportálatlan változók nem jelennek meg az aktuális héjon kívül, és a local változónak nincs értéke a függvényen kívül. Az utolsó teszt egyáltalán nem mutat értékeket, ez azért van, mert az exportált változókat nem osztják meg a héjak között, vagyis csak öröklődhetnek, és az öröklött értéket utólag nem befolyásolhatja a szülőhéj.
Ne feledje, hogy ez utóbbi viselkedés teljesen eltér a Windowsétól, ahol teljesen globális és az összes folyamat által megosztott rendszerváltozókat használhat.
Válasz
A folyamat körébe tartozik
A többi válaszadó segített megérteni, hogy a shell változó hatóköre folyamatokról szól és leszármazottaik .
Amikor olyan parancsot ír be, mint ls
, a parancssorba valójában folyamat elrendelése a ls
program futtatásához. Az új folyamat szülője a héja.
Bármelyik folyamatnak megvannak a maga “helyi” változói, amelyek: nem adják át gyermekfolyamatoknak. Beállíthat olyan “környezeti” változókat is, amelyek a következők: A export
használatával környezeti változó jön létre. Bármelyikben esetben a független folyamatok (az eredeti társaik) nem fogják látni a változót, csak azt ellenőrizzük, hogy milyen gyermek proc esszéinket lásd:
Tegyük fel, hogy van egy bash héja, amelyet “A-nak hívunk. Ön beírja a következőt: bash
, amely létrehoz egy gyermekfolyamat-bash héjat, amelyet “B-nek hívunk. Bármi, amit export
-nek hívtál A-ban, továbbra is B-ben lesz beállítva.
Most, a B-ben azt mondja, hogy FOO=b
. Két dolog egyike fog történni:
- Ha B nem kapott (A-tól) egy
FOO
nevű környezeti változót, akkor létrehoz egy helyi változót. B gyermekei nem kapják meg (hacsak B nem hívja megexport
). - Ha B fogadja (A-tól) egy
FOO
nevű környezeti változót, módosítja magának és később villás gyermekei . B gyermekei látni fogják azt az értéket, amelyet B rendelt. Ez azonban egyáltalán nem érinti A-t.
Itt “gyors bemutató .
FOO=a # set "local" environment variable echo $FOO # "a" bash # forks a child process for the new shell echo $FOO # not set exit # return to original shell echo $FOO # still "a" export FOO # make FOO an environment variable bash # fork a new "child" shell echo $FOO # outputs "a" FOO=b # modifies environment (not local) variable bash # fork "grandchild" shell echo $FOO # outputs "b" exit # back to child shell exit # back to original shell echo $FOO # outputs "a"
Mindez megmagyarázza az eredeti problémámat: A GEM_HOME
parancsot beállítottam a shellembe, de amikor hívtam bundle install
, ami létrehozott egy gyermekfolyamatot. Mivel nem használtam a export
-et, a gyermekfolyamat nem kapta meg az “s” héjat div id = “f355246fd1”>
.
Exportálás visszavonása
A export -n FOO
.
export FOO=a # Set environment variable bash # fork a shell echo $FOO # outputs "a" export -n FOO # remove environment var for children bash # fork a shell echo $FOO # Not set exit # back up a level echo $FOO # outputs "a" - still a local variable
Megjegyzések
- Amikor azt mondod ” módosítani fogja saját maga és gyermekei számára ” Önnek tisztáznia kell, hogy csak azok a gyermekek hozták létre, amelyek a módosítás után látni fogja a módosított értéket.
- @enzotib – jó pont. Frissítve.
Válasz
A legjobb magyarázat, amit az exportálásról találok:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_02.html
Az alhéjban vagy gyermekhéjban beállított változó csak az alhéj, amelyben meghatározták. Az exportált változó valójában környezeti változóvá válik. Tehát az egyértelműség érdekében a bundle install
végrehajtja a saját shelljét, amely nem látja a $GEM_HOME
-et, hacsak nem environment
változó, más néven exportálva.
Itt megnézheti a változó hatókörének dokumentációját:
http://www.tldp.org/LDP/abs/html/subshells.html
Megjegyzések
- Ah, ezért tévesen használtam a ” környezeti változó ” a
FOO=bar
számára; a következőt kell használnia:export
hogy eggyé váljon. A kérdés ennek megfelelően javítva. - Vessen egy pillantást az általam hozzáadott linkre.
Válasz
A várakozásoknak megfelelően változó hatókörök hierarchiája van.
Környezet
A legkülső hatókör a környezet. Ez az egyetlen hatókör az operációs rendszer kezeli, és ezért garantáltan létezik minden folyamat számára. A folyamat indításakor a a szülő környezetének másolata, amely után a kettő függetlenné válik: a gyermek környezetének módosítása nem változtatja meg a szülő környezetét, és a szülő környezetének módosítása nem változtatja meg a már meglévő gyermekét.
Shell változók
A shellek saját fogalommal rendelkeznek a változókról. A dolgok itt kissé zavarossá válnak.
Ha egy héjban lévő változóhoz értéket rendel, és ez a változó már létezik a környezetben, a környezeti változó megkapja az új értéket. Ha azonban a változó még nincs a környezetben, akkor shell változóvá válik. A héjváltozók csak a héjfolyamaton belül léteznek, hasonlóan ahhoz, ahogy a Ruby-változók csak a Ruby-szkripten belül léteznek. Soha nem öröklik őket a gyermeki folyamatok.
Itt jelenik meg a export
kulcsszó. A shell változót a shell folyamat környezetébe másolja, lehetővé téve a gyermek folyamatok öröklődését.
Helyi változók
A helyi változók olyan héjváltozók, amelyek az őket tartalmazó kódblokkokra vannak lefedve. A helyi változókat a typeset
kulcsszóval (hordozható) vagy local
vagy declare
(Bash ). A többi shell-változóhoz hasonlóan a helyi változókat sem a gyermekfolyamatok öröklik. A helyi változókat sem lehet exportálni.
FOO=bar
, akkor az megadja az aktuális shell folyamat értékét. Ha ezután futtatok egy olyan programot, mint a (bundle install
), az létrehoz egy gyermekfolyamatot, amely nem ‘ nem kap hozzáférést aFOO
. De ha azt mondtam, hogyexport FOO=bar
, akkor a gyermekfolyamat (és annak leszármazottai) hozzáférhetnek ehhez. Az egyikük viszont felhívhatja a (z)export FOO=buzz
-t, hogy megváltoztassa az utódok értékét, vagy csakFOO=buzz
, hogy az értéket csak magának változtassa meg . Ez igaz?