Sonuçta bash'ta “.” İle “kaynak” arasında bir fark var mı?


37

"" Arasındaki farkı arıyordum. ve "kaynak" yerleşik komutları ve birkaç kaynak (örneğin, bu tartışmada ve bash manpage) bunların aynı olduğunu göstermektedir.

Ancak, ortam değişkenleriyle ilgili bir problemin ardından bir test yaptım. Aşağıdakileri testenv.shiçeren bir dosya oluşturdum :

#!/bin/bash
echo $MY_VAR

Komut isteminde aşağıdakileri gerçekleştirdim:

> chmod +x testenv.sh
> MY_VAR=12345
> ./testenv.sh

> source testenv.sh
12345
> MY_VAR=12345 ./testenv.sh
12345

[1. formun boş bir dize döndürdüğünü unutmayın]

Dolayısıyla, bu küçük deney, sonuçta , bir "kaynak" komutu için, çocuk ortamının tüm değişkenleri ebeveyninden, "için" olduğu yerde miras aldığını ortaya koyuyor . o değil.

Am Ben bir şey eksik veya bunun bir belgesiz / kaldırılan özelliğidir edilir bash ?

[GNU bash, sürüm 4.1.5 (1) - sürüm (x86_64-pc-linux-gnu)]

Yanıtlar:


67

Kısa cevap

.Sorunuzda , ikinci komut ne kabuk yerleşik ne de sourceyerleşik kullanır. Bunun yerine, aslında komut dosyasını ayrı bir kabukta çalıştırıyorsunuz, diğer herhangi bir yürütülebilir dosyada olduğu gibi isimle çağırıyorsunuz. Bu (gerçi o değişkenlerin ayrı bir kümesi veriyor eğer ihracat bir değişken , üst kabukta, o bir alt süreç için bir ortam değişkeni olacak ve bu nedenle bir çocuğun Shell'in değişkenler dahil edilecektir ). /Bir boşluğa değiştirirseniz, bu onu .eşdeğer olan yerleşikle çalıştırır source.

Genişletilmiş Açıklama

Bu, sourcemevcut kabuktaki bir betiğin içeriğini (ve böylece mevcut kabuğun değişkenleriyle) yürüten kabuğun yerleşik sözdizimidir :

source testenv.sh

Bu, .aynı şeyi yapan yerleşikin sözdizimidir source:

. testenv.sh

Ancak, bu sözdizimi komut dosyasını yürütülebilir bir dosya olarak çalıştırır ve çalıştırmak için yeni bir kabuk başlatır:

./testenv.sh

Bu .yerleşik kullanmıyor . Aksine, .yürüttüğünüz dosya yolunun bir parçasıdır. Genel olarak, herhangi bir çalıştırılabilir dosyayı en az bir /karakter içeren bir adla çalıştırarak bir kabukta çalıştırabilirsiniz . Bir dosyayı geçerli dizinde çalıştırmak, bundan önce ./gelmesi en kolay yoldur. Geçerli dizininizde PATHdeğilse, komut dosyasını komutla çalıştıramazsınız testenv.sh. Bu, insanların bir sistem komutu veya PATHortam değişkeninde listelenen bazı dizinde bulunan başka bir dosyayı yürütmek istediklerinde, geçerli dizindeki dosyaları yanlışlıkla çalıştırmalarını engellemektir .

Bir dosyayı ada göre ( sourceveya ile değil .) çalıştırmak, yeni bir kabukta çalıştığından, kendi kabuk değişken kümesine sahip olacaktır. Yeni kabuk , ortam değişkenlerini çağıran işlemden (bu durumda etkileşimli kabuğunuzdur) miras alır ve bu ortam değişkenleri yeni kabukta kabuk değişkenleri haline gelir. Bununla birlikte, bir kabuk değişkeninin yeni kabuğa geçirilmesi için aşağıdakilerden birinin olması gerekir:

  1. Kabuk değişkeni dışa aktarılmış ve bunun bir ortam değişkeni olmasına neden olmuştur. Bunun için exportyerleşik kabuğu kullanın . export MY_VAR=12345Örneğinizde, değişkeni bir adımda ayarlamak ve dışa aktarmak için kullanabilirsiniz veya önceden ayarlanmışsa basitçe kullanabilirsiniz export MY_VAR.

  2. Kabuk değişkeni, çalıştırmakta olduğunuz komut için açıkça ayarlanır ve iletilir; bu, çalıştırılan komutun süresi için bir ortam değişkeni olmasını sağlar. Bu genellikle bunu başarır:

    MY_VAR=12345 ./testenv.sh

    Eğer MY_VARihraç edilmemiş bir kabuk değişkeni olduğunu, hatta çalışabilir testenv.shile MY_VARtarafından bir ortam değişkeni olarak geçirilen kendine ayarlama :

    MY_VAR="$MY_VAR" ./testenv.sh

./ Scriptler için Sözdizimi Çalışmak için Hashbang Hattı Gerektirir (Doğru)

Sizi adıyla bir yürütülebilir yukarıdaki gibi (ve ile çağırmak arada, o, unutmayın .ya sourceda çalıştırmak için kullanılan bir program kabuk neyi yerleşik ins kabuk), değil genellikle onu çalıştırdığınız kabuk ne göre belirlenir . Yerine:

  • İkili dosyalar için, çekirdek o belirli tipteki dosyaları çalıştıracak şekilde yapılandırılabilir. Dosyanın ilk iki baytını ne tür bir ikili çalıştırılabilir olduğunu gösteren "sihirli bir sayı" için inceler . Bu, çalıştırılabilir ikili dosyaların nasıl çalışabileceğidir.

    Bu, elbette, son derece önemlidir, çünkü bir betik, çalıştırılabilir bir ikili olan bir kabuk veya başka bir tercüman olmadan çalışamaz! Ayrıca, birçok komut ve uygulama, komut dosyaları yerine derlenmiş ikiliklerdir.

    ( #!"sihirli sayı" nın, çalıştırılabilir bir metni gösteren metin gösterimidir.)

  • Bir kabuk veya başka bir yorumlanmış dilde çalışması gereken dosyalar için ilk satır şöyle görünür:

    #!/bin/sh

    /bin/shprogramı çalıştırmak için başka bir kabuk veya tercüman kullanılması amaçlanan ile değiştirilebilir. Örneğin, bir Python programı şu satırla başlayabilir:

    #!/usr/bin/python

    Bu satırlara hashbang, shebang ve benzer birçok ad denir. Bu FOLDOC girişine bakın , bu Wikipedia makalesi ve #! / Bin / sh tercüman tarafından okundu mu? daha fazla bilgi için.

  • Bir metin dosyası ise çalıştırılabilir işaretlenir ve siz (gibi kabuğundan çalıştırmak ./filename) ama o değil ile başlayan #!, çekirdek bunu çalıştırmak için başarısız olur. Bununla birlikte, bunun gerçekleştiğini görünce, kabuğunuz adını bir kabuğa geçirerek çalıştırmayı deneyecektir . Hangi kabuğun üzerine yerleştirilmiş çok az gereksinim vardır ( "kabuk, kabuğunu çağırmaya eşdeğer bir komutu yerine getirecektir ..." ). Uygulamada , bazı mermiler - dahil * - başkalarının kullanımına başlarken, diğerleribash/bin/sh. Bundan kaçınmanızı ve bunun yerine bir hashbang satırı kullanmanızı şiddetle tavsiye ederim (veya komut dosyasını istediğiniz tercümana (örneğin, örneğin bash filename) geçirerek çalıştırın ).

    * GNU Bash kılavuzu , 3.7.2 Komut Arama ve Yürütme : "Bu yürütme, dosya yürütülebilir biçimde olmadığından ve dosya bir dizin olmadığından başarısız olursa, bir kabuk betiği olduğu ve kabuğun da açıklandığı gibi çalıştığı varsayılır. içinde kabuğu kodları ."


2
Faydalı bulduğum sourceşey, işlevlerin tekrar yüklenmesine veya başlatılmaya gerek kalmadan bash'tan erişilebilir olması. Örnek #!/bin/bash function olakease {echo olakease;}. Bir kere yükledikten sonra source file.shdoğrudan olakeasebash den arayabilirsiniz . Bundan gerçekten hoşlanıyorum. Kaynak daha sonra çok şey yükler, nokta .sadece yürütme içindir ve kullanım gibi bir şeydirbash file.sh
erm3nda

2
@ erm3nda .da bu davranışa sahiptir: . file.shve source file.shaynı şeyi, içinde tanımlanmış tutma fonksiyonları dahil olmak üzere aynı şeyi yapar file.sh. (Belki de düşünüyoruz ./file.shfarklı olan Ama bu yok. Değil kullanmak .yerleşiği yerine, .yolun bir parçasıdır.)
Eliah Kagan

Oh!, [Space] dosyasını dikkatlice okumadım. Çok teşekkür ederim.
erm3nda

13

Evet, bir şey kaçırıyorsun.

Sanırım '' kafasını karıştırıyorsun. Bu, şu anki dizinde olduğu gibi ./testenv.sh'de' anlamına gelir . Bu source(yerleşik bir komuttur) anlamına gelir . Öyleyse '.' sourceolacağı anlamına gelir . ./testenv.sh. Mantıklı olmak?

Öyleyse şunu dene:

MY_VAR=12345 
. ./testenv.sh

2
./Onu bulamadık eğer, o olmadan bash ilk PATH aracılığıyla bakacağız dosya, daha sonra geçerli dir deneyin tam olarak nerede söyler. Bash POSIX modunda çalışıyorsa ve dosyaya (yol gibi ./) bir yol sağlamazsanız , yalnızca PATH'de arama yapar ve geçerli dizin PATH'de değilse dosyayı bulamaz.
geirha

@geirha Evet, haklısınız, source(ve .) aslında komut dosyasını gerçekten çalıştırmıyor olsalar da ilk önce $ PATH öğesini kontrol edecekler . Benim (eski) yorumum yanlıştı.
Eliah Kagan,

Kısa ve noktaya +1
David Morales
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.