Bir Bash betiğini çalıştırmak yerine onu bulmak arasındaki fark nedir?


Yanıtlar:


344

Kısa cevap

Kaynak bir komut dosyası komutları çalışır geçerli kabuk süreci.

Yürütme bir komut dosyası bir komutları çalıştırır yeni kabuk süreci.

Komut dosyasının, çalışmakta olan kabuğunuzdaki ortamı değiştirmesini istiyorsanız, kaynağı kullanın. aksi takdirde yürütme kullanın.

Hala kafanız karıştıysa, lütfen okumaya devam edin.

terminoloji

Yürütülecek sözdizimi ve kaynak sözdizimi hakkında bazı genel karışıklıkları netleştirmek için:

./myscript

Bu , dosyanın çalıştırılabilir olması ve geçerli dizinde bulunması şartıyla yürütülür myscript . Baştaki nokta ve eğik çizgi ( ./) geçerli dizini gösterir. Bu gereklidir, çünkü geçerli dizin genellikle değildir (ve genellikle olmamalıdır) $PATH.

myscript

Dosya çalıştırılabilir ve içindeki bir dizinde bulunuyorsa bu işlem yürütülür .myscript$PATH

source myscript

Bu kaynak olacaktır myscript. Dosyanın çalıştırılabilir olması gerekmez, ancak geçerli bir kabuk betiği olmalıdır. Dosya geçerli dizinde veya içinde bir dizinde olabilir $PATH.

. myscript

Bu da kaynak olacaktır myscript. Bu "yazım" POSIX tarafından tanımlandığı şekliyle resmidir . Bash, noktaya sourcebir takma isim olarak tanımlandı .

gösteri

myscript.shAşağıdaki içeriği dikkate alın :

#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD

Önce betiği çalıştırmadan önce mevcut ortamı kontrol ederiz:

$ env | grep FOO
$ echo $PWD
/home/lesmana

Değişken FOOtanımlanmadı ve biz giriş dizinindeyiz.

Şimdi dosyayı çalıştırıyoruz :

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Çevreyi tekrar kontrol edin:

$ env | grep FOO
$ echo $PWD
/home/lesmana

Değişken FOOayarlanmadı ve çalışma dizini değişmedi.

Betik çıktısı açıkça değişkenin ayarlandığını ve dizinin değiştirildiğini gösteriyor. Daha sonra kontrol, değişkenin ayarlanmadığını ve dizinin değişmediğini gösterir. Ne oldu? Değişiklikler yeni bir kabukta yapıldı. Geçerli kabuk bir olurken yeni komut dosyasını çalıştırmak için kabuk. Komut dosyası yeni kabukta çalışıyor ve ortamdaki tüm değişiklikler yeni kabukta etkili oluyor. Senaryo tamamlandıktan sonra yeni kabuk imha edilir. Yeni kabukta çevreye yapılan tüm değişiklikler yeni kabukla imha edilir. Geçerli kabukta yalnızca çıktı metni yazdırılır.

Şimdi dosyayı kaynaklıyoruz :

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

Çevreyi tekrar kontrol edin:

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

FOO değişkeni ayarlanmıştır ve çalışma dizini değişmiştir.

Komut dosyasını kaynaklamak yeni bir kabuk oluşturmaz. Tüm komutlar geçerli kabukta çalıştırılır ve ortamdaki değişiklikler mevcut kabukta etkili olur.

Bu basit örnekte, çalıştırmanın çıktısının betiği almakla aynı olduğunu unutmayın. Bu mutlaka her zaman böyle değildir.

Başka Bir Gösteri

Aşağıdaki komut dosyasını düşünün pid.sh:

#!/bin/sh
echo $$

(özel değişken $$, geçerli çalışan kabuk işleminin PID'sine genişler)

İlk önce mevcut kabuğun PID'ini yazdırın:

$ echo $$
25009

Komut dosyasını kaynakla:

$ source pid.sh
25009

Komut dosyasını yürütün, PID’e dikkat edin:

$ ./pid.sh
25011

Tekrar kaynak:

$ source pid.sh
25009

Tekrar yürütün:

$ ./pid.sh
25013

Komut dosyasını çalıştırmanın aynı işlemle çalıştığını, komut dosyasını çalıştırmanın her zaman yeni bir işlem oluşturduğunu görebilirsiniz. Bu yeni işlem, betiğin çalıştırılması için oluşturulan yeni kabuktur. Komut dosyasını kaynaklamak yeni bir kabuk oluşturmaz ve bu nedenle PID aynı kalır.

özet

Komut dosyasını hem kaynak hem de yürütme, komutları satır satır yazmışsınız gibi satır satır komutları çalıştırır.

Farklılıklar:

  • Ne zaman yürütmek bir açıyoruz senaryoyu yeni kabuk, daha sonra yeni bir kabuk kapatın, yeni kabuk komutları yazın mevcut kabuk geri çıkışını kopyalayın. Çevrede yapılacak herhangi bir değişiklik sadece yeni kabukta etkili olacaktır ve yeni kabuk kapatıldığında kaybolacaktır.
  • Ne zaman kaynak size komutları yazdığınız senaryoyu akım kabuk. Çevrede yapılan değişiklikler geçerli olacak ve mevcut kabuğunuzda kalacaktır.

Komut dosyasının, çalışmakta olan kabuğunuzdaki ortamı değiştirmesini istiyorsanız, kaynağı kullanın. aksi takdirde yürütme kullanın.


Ayrıca bakınız:


2
Kaynak kullanımının bir kullanımı, komut dosyalarınız için basit bir yapılandırma dosyası biçimi oluşturmaktır. Çeşitli değişkenleri varsayılan değerlere ayarlayarak başlarsınız ve sonra myscript.conf - gibi bir kaynakta kaynak yaparsınız ve bu kaynak kodlu komut dosyası, istediğiniz değerleri geçersiz kılan atama ifadelerine sahip olabilir. Kaynak komut dosyası # / bin / bash ile başlamadığından, doğrudan çalıştırılması teşvik edilmez.
LawrenceC

Böylece kaynak onu küresel bir kapsamda çalıştırmaya benziyor ve yürütme yeni bir yerel kapsam yaratıyor. Bu, bir komut dosyasındaki bir işleve genişletilebilir mi? Bir işlevi yürütmek (normal olarak) veya "kaynaklamak"?
aliteralmind

2
Kullanarak source myscript.shve arasında bir fark var mı . myscript.sh?
Holloway

2
bash kullanıyorsanız pratikte hiçbir fark yoktur. kaynak bash ile işaret eden bir diğer addır.
lesmana

1
İnsanlar böyle ayrıntılı örnekler verdiklerinde onu seviyorum, böylece kendim gibi Linux yenilerini bile anlayabiliyorum. Teşekkürler!
Julius

21

Bir betiği çalıştırmak, onu ayrı bir alt süreçte çalıştırır, yani betiği işlemek için ayrı bir kabuk örneği çağrılır. Bu komut tanımlanan herhangi bir ortam değişkenleri, vb anlamına gelir olamaz üst (akım) kabuk olarak güncellenir.

Bir betiği kaynaklamak, mevcut kabuğun kendisi tarafından ayrıştırıldığı ve yürütüldüğü anlamına gelir. Senaryonun içeriğini yazmış gibisin. Bu nedenle, kaynak kodun çalıştırılmasının çalıştırılabilir olması gerekmez. Ama elbette yürütüyorsanız çalıştırılabilir olması gerekir.

Geçerli kabukta konumsal argümanlarınız varsa, bunlar değişmez.

Yani a.shiçeren bir dosya varsa :

echo a $*

ve ben:

$ set `date`
$ source ./a.sh

Gibi bir şey alıyorum:

a Fri Dec 11 07:34:17 PST 2009

Buna karşılık:

$ set `date`
$ ./a.sh

bana verir:

a

Umarım yardımcı olur.


5
Her ne kadar bu cevabı her yönüyle doğru bulsam da, bunu anlamakta zorlanıyorum, çünkü bence, kaynak bulma ve yürütme farkından bile daha kafa karıştırıcı olan başka bir konsept (konumsal parametreleri belirleme) kullanarak gösteriliyor.
lesmana,

9

Sourcing aslında komut dosyasının her satırını komut isteminde birer birer yazmakla aynıdır ...

Yürütme yeni bir işlem başlatır ve ardından komut dosyasının her satırını çalıştırır, yalnızca geçerli ortamı döndürdüğü şekilde değiştirir.


6

Yukarıdakilere ek olarak, betiğin ./myscriptdosya myscript için yürütme izni gerektirdiği şekilde yürütülmesi, kaynak bulma için yürütme izni gerektirmez. Bu yüzden chmod +x myscriptdaha önce gerekli değilsource myscript


2
Doğru, ama bu bir problemse, her zaman koşabilirsin bash myscript.
Daniel Beck

5

Kaynaklama, kodda tanımlanan tüm ekstra değişkenleri alır.
Eğer konfigürasyonlarınız veya fonksiyon tanımlarınız varsa, kaynak yapmalı ve çalıştırmamalısınız. İnfazlar ebeveynlerin ortamından bağımsızdır.


3

Eğer doğru hatırlıyorsam, betiğin çalıştırılması, #!komut dosyasındaki satırda çalıştırılabilir dosyayı çalıştırır (genellikle yeni bir kabuk başlatılır ve betiği olduğu gibi yeni kabuğa etkili bir şekilde ekler #!/bin/sh);
oysa, betiğin kaynak kodlaması, mevcut kabuk ortamınızdaki her satırı çalıştırır; bu, mevcut kabuğunuzu değiştirmek için yararlıdır (örneğin, kabuk işlevlerini tanımlamak ve ortam değişkenlerini dışa aktarmak için bir yol sağlar).


2

sourceKomut Resim komut yürütüldüğünde (çalıştırılabilir izni olan zorunlu değildir ) de mevcut ise, kabuk çevre ./temin yürütür yürütülebilir bir komut dosyası yeni kabuk.

Ayrıca, bu cevabı örneğin kontrol edin: https://superuser.com/a/894748/432100

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.