“Kaynak x”, “arasındaki fark nedir? x ”ve“ ./x ”Bash'te?


11

run.shAşağıdaki gibi bir bash kaynağım var ,

#!/bin/bash
if [ $# -ne 1 ]; then
    exit
fi
...

iki şekilde yürüttüğümde farklı davranışlar var. İlk yol,

source run.sh

Uygulamadan sonra terminali kapatır. İkinci yol,

./run.sh

bu komut dosyasını çalıştırmayı bitirecek ve terminalde kalacaktır. İkisi için de bir bash komut çıkmak için bir komut varsa Soruyorum source run.shve ./run.shyürütme. Ben de denedim return, hangi ./run.shidam altında iyi çalışmıyor .

Daha genel olarak, bunun neden gerçekleştiğiyle ve "kaynak" ile "." Arasındaki farkla ilgileniyorum. kod yürütme için?

Yanıtlar:


16

Cevap vermeden önce bazı açıklamalara ihtiyaç olduğunu düşünüyorum. Aşağıdaki üç satırı inceleyelim:

source run.sh
. run.sh
./run.sh

İlk iki satır tamamen aynıdır: .aslında bir takma addır source. Ne sourceyapar için, geçerli bağlamda dolayısıyla bir çağrı shell script çalıştırarak olan exitkabuğu çıkılacak.

Ancak üçüncü satırın (sizi şaşırtan) diğer satırlarla hiçbir ilgisi yoktur. ./run.shyalnızca bir yoldur ve (örneğin) /home/user/run.shveya ile aynıdır /usr/bin/something. Kabuktaki komutların bir boşlukla ayrıldığını daima unutmayın. Yani, bu durumda, komut değil ., ama ./run.sh: bu bir alt kabuğun yürütüleceği ve exitsadece alt kabuğa etki edeceği anlamına gelir .


5

Üç yol:

Komut dosyasını bir işleve ekleyebilir ve yalnızca return komutunu kullanabilirsiniz.

#!/usr/bin/env bash
main() {
    ...
    return 1
    ...
}
main "$@"

Komut dosyasının etkileşimli bir kabuk tarafından kaynaklanıp kaynaklanmadığını test edebilirsiniz.

if [[ $- = *i* ]]; then
    return 1
else
    exit 1
fi

Geri dönmeyi deneyebilir ve başarısız olursa çıkın.

return 1 2>/dev/null || exit 1

Sihirli büyünün nasıl $- = *i* çalıştığına dair ipuçları var mı?
deadbeef404

@ deadbeef404 Özel parametre -şu anda etkin seçenek bayraklarını tutar. Test, -ibayrağın etkin olup olmadığını kontrol eder . Bkz. Gnu.org/software/bash/manual/html_node/Special-Parameters.html
geirha

1

'Kaynak' komutunu 'include' ifadesindeki gibi düşünün. Argümanın içeriğini alır ve doğrudan yönetiliyormuş gibi çalıştırır. Bu durumda komutunuz 'run.sh' argümanıyla 'source' olur ve run.sh komutunu komut satırınıza tam olarak run.sh içeriğini yazmış gibi yürütülür.

'./Run.sh' komutunu çalıştırdığınızda, './run.sh' komutunuzdur ve argümanı yoktur. Bu dosya düz metin olduğundan ve ikili olmadığından, kabuğunuz shebang'da (ilk satırda '#!') Bir tercüman arar ve '/ bin / bash' bulur. Böylece kabuğunuz yeni bir bash örneği başlatır ve run.sh içeriği bu yeni örneğin içinde çalıştırılır.

İlk durumda, bash 'exit' komutuna ulaştığında, komut satırına yazmışsınız gibi yürütülür. İkinci durumlarda bash işleminde çalıştırılır ve kabuğunuz sadece bu bash örneği bir 'exit' komutu alır.

Bash içine bir satır yazdığınızda, ilk boşluktan önceki herhangi bir şey komut olarak kabul edilir ve sonraki her şey bağımsız değişken olarak değerlendirilir. Komuta '.' "kaynak" ın takma adıdır. Koştuğunda '. run.sh 'the'. bağımsız değişkenlerinden bir boşlukla ayrıldığı için tek başına bir komuttur. './Run.sh' komutunu çalıştırdığınızda komutunuz './run.sh' ve '.' Komutudur. '.' ile run.sh komutunun göreli yolunun bir parçasıdır. mevcut klasörünüzü temsil eder.


Kabuk / bash betikleri ile daha iyi olmak isteyen bir C / C ++ programcısıysanız, bu mükemmel cevaptır.
Justin
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.