Yürütme exitbir kabuktaki bir tuzak olduğunu:
#!/bin/bash
function calc { echo 42; exit 1; }
echo $(calc)
Komut dosyası 42 yazdırır, alt kabuktan dönüş koduyla çıkar 1ve komut dosyasıyla devam eder. echo $(CALC) || exit 1Geri dönüş kodu, geri dönüş kodundan echobağımsız olarak 0 olduğundan , aramanın değiştirilmesi bile yardımcı olmaz calc. Ve calcönce idam edilir echo.
Daha da şaşırtıcı olanı , aşağıdaki senaryoda olduğu gibi yerleşik yapıya exitsarılarak etkisini engelliyor local. Bir giriş değerini doğrulamak için bir fonksiyon yazdığımda problemin üstesinden geldim. Örnek:
20141211.logBugün "year month day.log" adlı bir dosya oluşturmak istiyorum . Tarih, makul bir değer sağlayamayan bir kullanıcı tarafından girilir. Bu nedenle, benim fonksiyonumda kullanıcı girişinin geçerliliğini doğrulamak için fnamedönüş değerini kontrol ediyorum date:
#!/bin/bash
doit ()
{
local FNAME=$(fname "$1") || exit 1
touch "${FNAME}"
}
fname ()
{
date +"%Y%m%d.log" -d"$1" 2>/dev/null
if [ "$?" != 0 ] ; then
echo "fname reports \"Illegal Date\"" >&2
exit 1
fi
}
doit "$1"
İyi görünüyor. Komut dosyasını adlandırın s.sh. Kullanıcı betiği ile çağırırsa ./s.sh "Thu Dec 11 20:45:49 CET 2014", dosya 20141211.logoluşturulur. Bununla birlikte, kullanıcı yazarsa ./s.sh "Thu hec 11 20:45:49 CET 2014", komut dosyası çıktısını alır:
fname reports "Illegal Date"
touch: cannot touch ‘’: No such file or directory
Satır fname…, alt kabukta hatalı giriş verilerinin tespit edildiğini söylüyor. Fakat çizginin exit 1sonunda local …asla tetiklenmez, çünkü localdirektif daima geri döner 0. Bunun nedeni local, daha sonra çalıştırılmasının $(fname)ve dönüş kodunun üzerine yazmasının nedenidir. Ve bu nedenle, komut dosyası devam eder ve touchboş bir parametre ile çağırır . Bu örnek basittir ancak bash'ın davranışı gerçek bir uygulamada oldukça kafa karıştırıcı olabilir. Biliyorum, gerçek programcılar locals kullanmıyor.
localAçıklığa kavuşturmak için: Komut dosyası olmadan geçersiz bir tarih girildiğinde komut dosyası beklendiği gibi iptal edilir.
Düzeltme çizgiyi gibi bölmektir
local FNAME
FNAME=$(fname "$1") || exit 1
Garip davranış, bash'ın localman sayfasındaki belgelere uyuyor : "Bir fonksiyon dışında yerel kullanılmadığı, geçersiz bir ad sağlandığı veya isim salt okunur bir değişken olmadığı sürece dönüş durumu 0'dır."
Hata olmamasına rağmen, bash'ın davranışının tersine dönük olduğunu hissediyorum. İnfazın sırasının farkındayım local, yine de kesilmiş bir ödevi maskelememeliyim.
İlk cevabım bazı yanlışlıklar içeriyordu. Mikeserv ile yapılan açıklayıcı ve derinlemesine bir tartışmadan sonra (bunun için teşekkür ederim) Onları tamir etmeye gittim.