it-swarm-tr.com

Shell betiği yürütmenin farklı yolları

Bir komut dosyasını yürütmenin birkaç yolu vardır, bildiğim komutlar şunlardır:

/path/to/script # using the path (absolute or relative)
. script        # using the . (dot)
source script   # using the `source` command

Bundan daha fazlası mı? Aralarındaki farklar nelerdir? Birini değil diğerini kullanmam gereken durumlar var mı?

44
phunehehe

Başka bir yol da yorumlayıcıyı çağırmak ve betiğin yolunu ona aktarmaktır:

/bin/sh /path/to/script

Nokta ve kaynak eşdeğerdir. (EDIT: hayır, onlar değil: KeithB başka bir cevap üzerine bir yorumda belirttiği gibi, "." Sadece bash ile ilgili kabuklarda çalışır, burada "source" hem bash hem de csh ile ilgili kabuklarda çalışır.) -place (komut dosyasını kopyalayıp yapıştırdığınız gibi). Bu, koddaki tüm işlevlerin ve yerel olmayan değişkenlerin kalacağı anlamına gelir. Ayrıca, komut dosyasının bir dizine cd yaparsa, işiniz bittiğinde hala orada olacaksınız demektir.

Bir komut dosyasını çalıştırmanın diğer yolları onu kendi alt kabuğunda çalıştırır. Koddaki değişkenler tamamlandığında hala canlı değildir. Komut dosyası dizinleri değiştirdiyse, arama ortamını etkilemez.

/ path/to/script ve/bin/sh script biraz farklıdır. Genellikle, bir komut dosyasında başlangıçta şöyle görünen bir "Shebang" vardır:

#! /bin/bash

Bu, kod yorumlayıcısının yoludur. Çalıştırdığınızda sizden farklı bir yorumlayıcı belirtirse, farklı davranabilir (veya hiç çalışmayabilir).

Örneğin, Perl komut dosyaları ve Ruby komut dosyaları (sırasıyla) ile başlar:

#! /bin/Perl

ve

#! /bin/Ruby

Bu komut dosyalarından birini /bin/sh script, o zaman hiç çalışmaz.

Ubuntu aslında bas Kabuğunu kullanmaz, ancak çizgi adı verilen çok benzer bir şeydir. Bash gerektiren komut dosyaları /bin/sh script çünkü kısa süre önce yorumlayıcı kullanarak bash betiği çağırdınız.

Komut dosyasını doğrudan çağırmak ve komut dosyası yolunu yorumlayıcıya iletmek arasındaki bir diğer küçük fark, komut dosyasının doğrudan çalıştırmak için yürütülebilir olarak işaretlenmesi, ancak yolu yorumlayıcıya ileterek çalıştırılmaması gerektiğidir.

Başka bir küçük varyasyon: eval ile bir komut dosyası yürütmek için bu yollardan herhangi birine ön ek ekleyebilirsiniz, böylece

eval sh script
eval script
eval . script

ve bunun gibi. Aslında hiçbir şeyi değiştirmez, ama tam olarak dahil edeceğimi düşündüm.

32
Shawn J. Goff

Çoğu kişi, komut dosyasına aşağıdakileri hata ayıklama bayrakları ekleyerek Shell komut dosyalarında hata ayıklama yapar:

set -x     # Print command traces before executing command.
set -v     # Prints Shell input lines as they are read.
set -xv    # Or do both

Ancak bu, dosyayı set -x, dosyayı kaydedin ve ardından dosyayı yürütün. Ardından işiniz bittiğinde aynı adımları izlemeniz ve set -x, vb. Bu sıkıcı olabilir.

Tüm bunları yapmak yerine, komut satırında hata ayıklama bayraklarını ayarlayabilirsiniz:

$ bash -x ~/bin/ducks
+ du -cks -x dir1 dir2 dir3 file1 file2 file3
+ sort -n
+ tail .ducks
123 etc
424 bin
796 total



$ sh -xv ~/bin/ducks  
#!/usr/bin/env bash

# Find the disk hog
# Borrowed from http://oreilly.com/pub/h/15
...
...
9
Stefan Lasiewski

Shawn J. Goff birçok iyi noktaya değindi, ancak tüm hikayeyi içermedi:

Ubuntu aslında bas Kabuğunu kullanmaz, ancak çizgi adı verilen çok benzer bir şeydir. Bash gerektiren komut dosyaları, /bin/sh Komut dosyası kullanılarak çağrıldığında biraz yanlış çalışabilir, çünkü kısa çizgi yorumlayıcısını kullanarak bir bash komut dosyası çağırdınız.

Birçok sistem komut dosyasının (init.d,/etc ve benzeri gibi) bir Shebang'ı vardır #!/bin/sh, Ancak /bin/sh Aslında başka bir Kabuğa sembolik bir bağlantıdır - eski zamanlarda /bin/bash, Bugünlerde /bin/dash. Ancak bunlardan biri /bin/sh Olarak çağrıldığında, farklı davranırlar, yani POSIX uyumluluk moduna bağlı kalırlar.

Bunu nasıl yapıyorlar? Nasıl çağrıldıklarını denetlerler.

Bir kabuk komut dosyasının kendisi nasıl çağrıldığını test edebilir ve buna bağlı olarak farklı şeyler yapabilir mi? Evet yapabilir. Böylece onu çağırmanın yolu her zaman farklı sonuçlara yol açabilir, ancak elbette sizi rahatsız etmek için nadiren yapılır. :)

Genel bir kural olarak: bash gibi belirli bir Kabuk öğreniyorsanız ve bir bash öğreticisinden komutlar yazıyorsanız, aksi belirtilmedikçe #!/bin/bash Yerine #!/bin/sh Başlığına koyun. Aksi takdirde komutlarınız başarısız olabilir. Ve kendiniz bir komut dosyası yazmadıysanız, bir Kabuk (./foo.sh, bar/foo.sh) Tahmin etmek yerine doğrudan çağırın (sh foo.sh, sh bar/foo.sh). Shebang doğru Kabuğu çağırmalıdır.

Ve işte başka iki tür çağırma:

cat foo.sh | dash
dash < foo.sh
7
user unknown

. ve source, bir alt işlem üretmemesi, ancak geçerli Kabukta komut yürütmesi bakımından eşdeğerdir. Komut dosyası ortam değişkenlerini ayarladığında veya geçerli çalışma dizinini değiştirdiğinde bu önemlidir.

Yolu kullanma veya /bin/sh, komutların yürütüldüğü yeni bir işlem oluşturur.

5
mouviciel
sh script
bash script

Daha fazlası varsa düşünüyorum ...

. ve source aynı. Yürütmeden sonra script içindeki ortam değişiklikleri korunur. Genellikle, bir Bash kitaplığını kaynaklamak için kullanılır, böylece kitaplık birçok farklı komut dosyasında yeniden kullanılabilir.

Ayrıca geçerli dizini tutmak için iyi bir yoldur. Komut dosyasındaki dizini değiştirirseniz, o komut dosyasını yürüttüğünüz Kabuk'ta uygulanmaz. Ancak, onu çalıştırmak için kaynak yaparsanız, komut dosyası çıktıktan sonra geçerli dizin korunacaktır.

2
livibetter

. ve kaynak en azından zsh içinde biraz farklı (kullandığım şey bu)

source file

İşleri iken

. file

değil, ihtiyacı var

. ./file
1
bollovan
. ./filename
# ( dot space dot slash filename )

Dizin yolda olmadığında komut dosyasını geçerli Kabuk'ta çalıştırır.

1
jrh_enginnering

" serland exec " farklı bir yol olarak sayılıyor mu? Userland exec kodu yükler ve execve () sistem çağrısı kullanmadan çalıştırmasını sağlar.

1
Bruce Ediger