Kaynak ('.' Veya 'kaynak') ve bash bir dosya yürütme arasındaki fark nedir?


76

Böyle bir betiği çalıştırmak arasındaki fark nedir:

./test.sh

ve böyle bir betiği çalıştırmak:

. test.sh?

Bir fark olup olmadığını bulmak için basit, iki satırlı bir komut dosyası denedim:

#!/bin/bash
ls

Ancak her iki . test.shve ./test.shaynı bilgiyi döndü.


Bunun bir kopyası olması için özür dileriz - daha fazla araştırma yapıldığında, "bash" yerine "bash noktası" nı arayarak alakalı bilgiler içeren bazı sayfalar buldum.
Natan

3
Tıpkı test.shaynı değildir ./test.sh(ilk bir çağırır PATHarama), bu yüzden vardır . test.shve . ./test.shaynı şekilde farklı (eski bir çağırır PATHarama). Bir çok mermi , yol araması yaparken .sonunda örtük olarak dahil olmuş gibi görünmektedir , ancak bu davranış standart değildir. Böylece, vs ve vs karşılaştırmak daha doğrudur . PATH.test.sh. test.sh./test.sh. ./test.sh
jw013,

Yanıtlar:


83

./test.shtest.shayrı bir program olarak çalışır . Dosyayla test.shbaşlarsa bash betiği olabilir #!/bin/bash. Fakat tamamen başka bir şey olabilir.

. ./test.shDosyanın kodunu test.shçalışan bash örneğinin içinde çalıştırır. İçerik dosyası satır test.shyerine metin olarak eklenmiş gibi çalışır . ./test.sh. (Neredeyse: değeri $BASH_LINENOve returnyerleşimin davranışı gibi farklı birkaç ayrıntı vardır .)

source ./test.sh. ./test.shbash ile aynıdır (diğer kabuklarda, sourcebiraz farklı olabilir veya tamamen mevcut olmayabilir; .çünkü POSIX standardındadır).

Ayrı ./test.shbir komut dosyası ile .yerleşik bir komut dosyası çalıştırma ve test.shiçerme arasındaki en yaygın fark , komut dosyası bazı ortam değişkenlerini ayarlarsa, ayrı bir işlemle, yalnızca alt işlemin ortamının ayarlanmış olmasıdır, oysaki komut dosyası dahil edildiğinde, ortam tek kabuğun işlemi ayarlanır. Bir çizgi eklerseniz foo=bariçinde test.shve echo $fooçağıran komut sonunda, farkı göreceksiniz:

$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo

$ . ./test.sh
$ echo $foo
bar

17
Ayrıca echo $$betiğe eklendiğinde aradaki fark oldukça açık. $$Değişken akım kabuğun PID tutar.

1
Başka bir kullanım senaryosu, . ./test.shtest.sh içinde açıklanan işlevleri kullanmak için çağrıyı başka bir kabuk betiğinin içinden kullanmaktır. Yani, sadece ayarlayabileceğiniz değişkenler değil, bu şekilde bash veya başka bir betikten çağrılabilen yeni fonksiyonlar da yaratabilirsiniz. . /usr/libexec/company/tools; custom_command "variable"
Rqomey

9

Bir betiği ilk kez çalıştırmak, onu bir alt işlem olarak çalıştırır. Kaynaklama (ikinci yol) ise komut dosyasını tüm komutlarını geçerli kabuğa girmiş gibi çalıştırır - komut dosyası bir değişken ayarlarsa, komut dosyası kalırsa, komut dosyası çıkarsa oturumunuz kapanır. help .Dokümantasyon için bakınız .


3

Benim hatırladığım bir diğer şey, böyle bir takma adınız varsa:

# add into .bashrc_aliases
alias ls='ls -lht'

./test.shNormal bir lsçıktı (ve mevcut kabuğundan farklı bir PID ile) elde edersiniz :

auraham@pandora:~/iso$ ./test.sh 
dsl-4.4.10.iso  test.sh
3136 # PID

İle . test.shveya . ./test.shdaha ayrıntılı bir çıktı elde edersiniz (ve mevcut kabukla aynı PID'yi alırsınız):

auraham@pandora:~/iso$ echo $$
2767 # shell PID

auraham@pandora:~/iso$ . test.sh 
total 50M
drwxrwxr-x  2 auraham auraham 4.0K Jul 30 15:41 .
-rwxrwxr-x  1 auraham auraham   32 Jul 30 15:41 test.sh
drwxr-xr-x 50 auraham auraham 4.0K Jul 30 15:30 ..
-rw-rw-r--  1 auraham auraham  50M Jul 28 17:24 dsl-4.4.10.iso
2767 # PID

Bunu Sonra'ya ekleyebilirsiniz .bashrc if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases fi , takma adlarınızı içine yerleştirin .bash_aliases.
auraham

Tabii ki, fakat hala aliasanahtar kelimeyi kullanmak zorunda değil misiniz ? (Belki bu sadece sizin gönderimdeki bir hata - 3. satırda?)
Emanuel Berg

Tamamen doğru, benim hatam. Thanks @EmanuelBerg
auraham

-1

source(Veya .) benim için ana kullanım bash işlevleridir .

Pek çok fonksiyona sahip komut dosyalarım var ve hepsini de yanımda yürütüyorum .bashrc. İşlevleri sık kullandığım "hale" komutları.


Her üç yöntemi de .bashrc - source, betiğin mutlak konumu ve komutun adını (betiği PATH klasörüne yerleştirerek) denedim - ve üç yöntem de işe yaradı.
Emanuel Berg
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.