Kabuk değişkenleri ve ortam değişkenleri arasındaki kullanım farkı nedir?


16

Aslında komut satırından erişebileceğim iki farklı değişken türü olduğunu bilmiyordum. Tek bildiğim, gibi değişkenleri beyan edebilmem:

foo="my dear friends"
bar[0]="one"
bar[1]="two"
bar[2]="three"

veya $ işareti ile bunlara erişme, örneğin:

echo $foo
echo ${bar[1]}

veya dahili değişkenleri kullanarak, örneğin:

echo $PWD
PATH=$PATH:"/usr/bin/myProg"

Şimdi iki (en azından?) Değişken türü olduğunu duydum: kabuk değişkenleri ve ortam değişkenleri.

  • İki farklı türe sahip olmanın amacı nedir?
  • Bir değişkenin hangi tür olduğunu nasıl bilebilirim?
  • Her biri için tipik kullanımlar nelerdir?


Yanıtlar:


14

Ortam değişkenleri name=value, program ne olursa olsun var olan çiftlerin bir listesidir (kabuk, uygulama, arka plan programı…). Genellikle alt süreçler tarafından miras alınır (a fork/ execsekans tarafından oluşturulur ): alt süreçler üst değişkenlerin kendi kopyalarını alırlar.

Kabuk değişkenleri yalnızca kabuk bağlamında bulunur. Sadece alt kabuklarda kalıtsaldırlar (yani kabuk bir execoperasyon olmadan çatallandığında ). Kabuk özelliklerine bağlı olarak, değişkenler yalnızca ortam gibi basit dizeler değil, aynı zamanda diziler, bileşik, tamsayı veya kayan nokta gibi yazılan değişkenler de olabilir.

Bir kabuk başladığında, üst öğesinden devraldığı tüm ortam değişkenleri de kabuk değişkenleri haline gelir (kabuk değişkenleri olarak geçersiz olmadıkları ve IFSbazı kabuklar tarafından sıfırlanan diğer köşe durumları dışında ), ancak bu devralınan değişkenler dışa aktarılır 1 olarak etiketlenir . Bu, kabuk tarafından ayarlanan potansiyel olarak güncellenmiş değere sahip çocuk süreçleri için kullanılabilir kalacakları anlamına gelir. Kabuk altında oluşturulan ve exportanahtar sözcükle dışa aktarılmış olarak etiketlenen değişkenlerde de durum budur .

Dizi ve diğer karmaşık tür değişkenleri, adları ve değerleri name=valuekalıba dönüştürülmedikçe veya kabuğa özgü bir mekanizma yerinde olmadığı sürece dışa aktarılamaz (örn: bashortamdaki dışa aktarma işlevlerini rcve esdiziler gibi bazı egzotik, POSIX olmayan kabukları dışa aktarabilir ve dışa aktarabilir ).

Bu nedenle, ortam değişkenleri ve kabuk değişkenleri arasındaki temel fark kapsamlarıdır: ortam değişkenleri globalken dışa aktarılmamış kabuk değişkenleri kod için yereldir.

Ayrıca, modern kabukların (en azından kshve bash) üçüncü bir kabuk değişkenleri kapsamını desteklediğini unutmayın. İle fonksiyonların yaratılan değişkenler typesetanahtar kelimeyi fonksiyonu (işlev bildirildi yön / sağlayan altında bu özelliği devre dışı bırakır yereldir kshve kalıcılık davranışı arasındaki farklıdır bashve ksh). Bkz. Https://unix.stackexchange.com/a/28349/2594

1 Modern kabukları sevmeye Bu durum ksh, dash, bashve benzeri. Eski Bourne kabuğu ve Bourne olmayan sözdizimi kabukları cshfarklı davranışlara sahiptir.


1
Çocuklar ebeveynlerinin bir çatalı (tam bir kopyası) olarak yaratıldığından, her şey çocuk süreçleri tarafından miras alınır. Ortam değişkenleriyle ilgili nokta, execve()sistem çağrısına aktarılmalarıdır (bu nedenle ( aynı işlemde) diğer komutların yürütülmesi üzerindeki verileri devam ettirmek için kullanılır ).
Stéphane Chazelas

Tüm ortam değişkenleri kabuk değişkenlerine çevrilmez. Yalnızca kabuk değişkeni adı olarak geçerli olanlar (ve IFSbazı kabuklarda olduğu gibi birkaç istisna dışında ).
Stéphane Chazelas

Kabuklar rc, esadhoc kodlaması kullanarak dizileri dışa aktarabilir. bashve rcayrıca ortam değişkenlerini kullanarak işlevleri dışa aktarabilir (yine özel bir kodlama kullanarak).
Stéphane Chazelas

İçinde ksh93, typesetkapsamı function foo { ...; }Bourne ( foo() cmd) sözdizimiyle değil, yalnızca sözdizimiyle bildirilen işlevlerde kısıtlar (ve diğer kabuklarda olduğu gibi dinamik olmayan statik kapsam belirleme ).
Stéphane Chazelas

@ StéphaneChazelas İncelediğiniz için teşekkür ederiz! Yorumlarınızı dikkate almak için güncelleme güncellendi.
jlliagre

17

Kabuk değişkenleri

Kabuk değişkenleri, kapsamı geçerli kabuk oturumunda olan, örneğin etkileşimli kabuk oturumunda veya bir komut dosyasında bulunan değişkenlerdir.

Kullanılmayan bir ada bir değer atayarak bir kabuk değişkeni oluşturabilirsiniz:

var="hello"

Kabuk değişkenlerinin kullanımı, geçerli oturumdaki verileri takip etmektir. Kabuk değişkenlerinin adları genellikle küçük harflidir.

Ortam Değişkenleri

Ortam değişkeni, dışa aktarılan kabuk değişkenidir. Bu, yalnızca onu oluşturan kabuk oturumunda değil, aynı zamanda o oturumdan başlatılan herhangi bir işlem için de (yalnızca kabuklar değil) bir değişken olarak görüneceği anlamına gelir.

VAR="hello"  # shell variable created
export VAR   # variable now part of the environment

veya

export VAR="hello"

Bir kabuk değişkeni ihraç edildikten sonra, buna kaldırılırsa ya da onun "ihracat özelliği" (ile kaldırılana kadar kadar ihraç kalır export -niçinde bash), bu yüzden yeniden ihracat o gerek genellikle yoktur. Bir değişkenin ayarının kaldırılması unsetonu siler (ortam değişkeni olsun ya da olmasın).

Diziler ve ilişkilendirilebilir karmalar bashve diğer kabuklar ortam değişkenleri olarak dışa aktarılamaz. Ortam değişkenleri, değerleri dize olan basit değişkenler olmalıdır ve genellikle büyük harflerden oluşan adları vardır.

Ortam değişkenlerinin kullanımı, geçerli kabuk oturumundaki verileri izlemenin yanı sıra başlatılan herhangi bir işlemin bu verilerin bir parçası olmasına izin vermektir. Bunun tipik durumu PATH, kabukta ayarlanabilen ve daha sonra, programlara tam bir yol belirtmeden başlatmak isteyen herhangi bir program tarafından kullanılabilen ortam değişkenidir.

Bir işlemdeki ortam değişkenlerinin toplanması genellikle "işlemin ortamı" olarak adlandırılır. Her sürecin kendi ortamı vardır.

Ortam değişkenleri yalnızca "iletilebilir", yani bir alt süreç , üst işlemindeki ortam değişkenlerini hiçbir zaman değiştiremez ve bir alt işlem için başlatıldıktan sonra ortamı ayarlamaktan başka bir üst işlem, bir alt süreç.

Ortam değişkenleri env(argüman olmadan) ile listelenebilir . Bunun dışında, bir kabuk oturumunda dışa aktarılmamış kabuk değişkenleriyle aynı görünürler. Diğer programlama dillerinin çoğu genellikle "sıradan" değişkenleri ortam değişkenleriyle karıştırmaz (bu aşağıya bakın) , bu kabuk için biraz özeldir .

env geçerli oturumda ayarlamadan bir işlem ortamındaki bir veya birkaç ortam değişkeninin değerlerini ayarlamak için de kullanılabilir:

env CC=clang CXX=clang++ make

Bu make, ortam değişkeni CCdeğere clangve olarak CXXayarlandığında başlar clang++.

Bir işlem için ortamı temizlemek için de kullanılabilir :

env -i bash

Bu başlar, bashancak geçerli ortamı yeni bashişleme aktarmaz ( kabuk başlatma komut dosyalarından yenilerini oluşturduğu için yine de ortam değişkenleri olacaktır ).

Fark örneği

$ var="hello"   # create shell variable "var"
$ bash          # start _new_ bash session
$ echo "$var"   # no output
$ exit          # back to original shell session
$ echo "$var"   # "hello" is outputted
$ unset var     # remove variable

$ export VAR="hello"  # create environment variable "VAR"
$ bash
$ echo "$VAR"         # "hello" is outputted since it's exported
$ exit                # back to original shell session
$ unset VAR           # remove variable

$ ( export VAR="hello"; echo "$VAR" )  # set env. var "VAR" to "hello" in subshell and echo it
$ echo "$VAR"         # no output since a subshell has its own environment

Diğer diller

Çoğu programlama dilinde ortam değişkenlerini almayı ve ayarlamayı sağlayan kütüphane işlevleri vardır. Ortam değişkenleri basit bir anahtar / değer ilişkisi olarak saklandığından, genellikle dilin "değişkenleri" olmadığını unutmayın. Bir program, bir anahtara (ortam değişkeninin adı) karşılık gelen değeri (her zaman bir karakter dizesi olan) getirebilir, ancak daha sonra bu değeri bir tamsayıya veya dilin değere sahip olmasını beklediği herhangi bir veri türüne dönüştürmesi gerekir.

C, çevre değişkenleri kullanılarak erişilebilir getenv(), setenv(), putenv()ve unsetenv(). Bu yordamlarla oluşturulan değişkenler, C programının başlattığı herhangi bir işlemle aynı şekilde miras alınır.

Diğer diller, %ENVPerl'deki karma veya ENVIRONçoğu uygulamadaki ilişkisel dizi gibi aynı şeyi gerçekleştirmek için özel veri yapılarına sahip olabilir awk.


thx, zekice net bir açıklama. Dolayısıyla çevre, diğer programların yaşayabileceği ve her bir çevre değişkenini görebileceği büyük bir alan gibidir. Bazı programların özel değişkenleri vardır, kabukları gibi sadece kendileri görebilirler. ancak özel değişkenlerin "dışa aktarma" olarak adlandırılan herkes tarafından görülmesini sağlayacak bir mekanizma vardır. Eğer bu anlaşılırsa, emin olamadığım tek şey, aynı anda birden fazla ortam olup olmadığıdır.
köpekbalığı

@sharkant Çalışan her işlemin kendi ortamı vardır. Bu ortam, onu başlatan süreçten miras alınır. Farklı süreçlerin ortamları arasında asla "çapraz konuşma" yoktur. Bir işlemdeki ortam değişkenini değiştirmenin tek yolu, işlemin kendisini değiştirmesidir.
Kusalananda

anlayışımı kestirdiğin için teşekkürler. Her balık kendi balık kabının içinde. Diğer süreçleri ortaya çıkaran süreçlere ne dersiniz? Süreçler ve onların çocuk süreçleri tek bir ortamda mı yoksa her biri kendi içinde mi?
köpekbalığı

1
@sharkant Çoğu dilde ortam değişkenlerini alıp ayarlamanıza izin veren kütüphane işlevleri vardır. C, bu ile yapılır getenv(), setenv(), putenv()ve unsetenv(). Bu yordamlarla oluşturulan değişkenler, C programının başlattığı herhangi bir işlemle aynı şekilde miras alınır. Diğer diller, %ENVPerl'de olduğu gibi, aynı şey için özel veri yapılarına sahip olabilir .
Kusalananda

1
FWIW: exec*()işlev ailesi, yürütülen işlem için ortamı da ayarlayabilir.
Satō Katsura

5

Kabuk değişkenlerinin çoğaltılması zordur.

$ FOO=bar
$ FOO=zot
$ echo $FOO
zot
$ 

Ancak ortam değişkenleri çoğaltılabilir; bunlar sadece bir listedir ve bir liste yinelenen girişlere sahip olabilir. İşte envdup.cbunu yapmak için.

#include <err.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

extern char **environ;

int main(int argc, char *argv[]) {
    char **newenv;
    int envcount = 0;

    if (argc < 2) errx(64, "Usage: envdup command [args ..]");

    newenv = environ;
    while (*newenv++ != NULL) envcount++;

    newenv = malloc(sizeof(char *) * (envcount + 3));
    if (newenv == NULL) err(1, "malloc failed");
    memcpy(newenv, environ, sizeof(char *) * envcount);
    newenv[envcount]   = "FOO=bar";
    newenv[envcount+1] = "FOO=zot";
    newenv[envcount+2] = NULL;

    environ = newenv;
    argv++;
    execvp(*argv, argv);
    err(1, "exec failed '%s'", *argv);
}

Hangi ortam değişkenlerinin ayarlandığını bize göstermek envdupiçin derleyip çalıştırabileceğimiz env...

$ make envdup
cc     envdup.c   -o envdup
$ unset FOO
$ ./envdup env | grep FOO
FOO=bar
FOO=zot
$ 

Bu belki de sadece programların ne kadar iyi işlediğine dair hataları veya diğer tuhaflıkları bulmak için yararlıdır **environ.

$ unset FOO
$ ./envdup perl -e 'exec "env"' | grep FOO
FOO=bar
$ ./envdup python3 -c 'import os;os.execvp("env",["env"])' | grep FOO
FOO=bar
FOO=zot
$ 

Görünüşe göre Python 3.6, Perl 5.24 yapmazken, çiftler boyunca (sızan bir soyutlama) körü körüne geçer. Mermilere ne dersin?

$ ./envdup bash -c 'echo $FOO; exec env' | egrep 'bar|zot'
zot
FOO=zot
$ ./envdup zsh -c 'echo $FOO; exec env' | egrep 'bar|zot' 
bar
FOO=bar
$ 

Tanrım, sudosadece ilk çevre girişini sterilize bashedip ikincisi ile çalışırsa ne olur ? Merhaba PATHya da LD_RUN_PATHistismar et. Senin sudo(ve diğer her şeyin ?) O delik için mi? Güvenlik istismarları, çağrı programında "anekdot farkı" veya sadece "hata" değildir.


1
Bu doğru ancak anekdot bir fark ve tartışmalı değişkeni ayarlayan programın bir hatası.
jlliagre


0

Bir ortam değişkeni bir gibidir kabuk değişkeni , ancak özgü olmayan kabuk . Tüm işlemler Unix sistemleri var ortam değişkeni depolama . Çevre ve kabuk değişkenleri arasındaki temel fark şudur: O işletim sistemi tüm geçer kabuk ortam değişkenleri kabuk değişkenleri komutlar erişilemiyor oysa kabuk çalışır, çalıştırmak o programlara.

env –Komut, geçerli programı değiştirmeden başka bir programı özel bir ortamda çalıştırmanıza izin verir. Bağımsız değişken olmadan kullanıldığında, geçerli ortam değişkenlerinin bir listesini yazdırır. printenv –Komut, belirtilen ortam değişkenlerinin tümünü veya tümünü yazdırır. set –Komut kabuk değişkenlerini ayarlar veya ayarlar. Bağımsız değişken olmadan kullanıldığında, ortam ve kabuk değişkenleri ve kabuk işlevleri de dahil olmak üzere tüm değişkenlerin bir listesini yazdırır. unset –Komut kabuk ve ortam değişkenlerini siler. export –Komut ortam değişkenlerini ayarlar

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.