Milyen hatókörrel rendelkezhetnek a shell változók?

É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

  • Ah! OK, hadd ‘ s lássa, értem-e ezt. Ha a héjban azt mondom, hogy 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 a FOO. De ha azt mondtam, hogy export 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 csak FOO=buzz, hogy az értéket csak magának változtassa meg . Ez igaz?
  • @NathanLong Ez ‘ nem pontosan ez: az összes modern héjban egy változó vagy exportálódik (és így az érték bármilyen változása a leszármazottak környezetében tükröződik), vagy nem exportálják (vagyis a változó nincs a környezetben). Különösen, ha a változó már a környezetben van, amikor a héj elindul, akkor az exportálásra kerül.
  • Kicsit megzavart a ” mondat, ha gyermek változtasson meg egy változó értékét, a megváltozott érték csak számára látható, és az összes utána létrehozott folyamat megváltozik “. Helyesebb lenne azt mondani, hogy ” … láthatóvá válik számára, és minden leszármazott folyamata, amelyet e változás után hoztak létre ” – a másik A szülői folyamat gyermekeit, még azokat sem, akik a gyermekfolyamat után kezdődtek, ez nem érinti.

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 meg export).
  • 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.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük