Bir bash betiğinde hata ayıklamanın herhangi bir yolu var mı? Örneğin, "arama hattı 1", "arama hattı 2" gibi bir tür yürütme günlüğü yazdıran bir şey.
Bir bash betiğinde hata ayıklamanın herhangi bir yolu var mı? Örneğin, "arama hattı 1", "arama hattı 2" gibi bir tür yürütme günlüğü yazdıran bir şey.
Yanıtlar:
sh -x script [arg1 ...]
bash -x script [arg1 ...]
Bunlar, yürütülmekte olan şeyin izini verir. (Ayrıca cevabın alt kısmındaki 'Açıklama' bölümüne bakınız.)
Bazen, betik içindeki hata ayıklamayı kontrol etmeniz gerekir. Bu durumda, Cheeto'nun hatırlattığı gibi , şunları kullanabilirsiniz:
set -x
Bu hata ayıklamayı açar. Ardından aşağıdakilerle tekrar kapatabilirsiniz:
set +x
(Geçerli izleme durumunu $-, için geçerli bayrakları analiz ederek bulabilirsiniz x.)
Ayrıca, mermiler genellikle -n'yürütme yok' ve -v'ayrıntılı' mod için ' ' seçenekleri sunar ; Kabuğun betiğinizi çalıştırabileceğini düşünüp düşünmediğini görmek için bunları birlikte kullanabilirsiniz - bir yerlerde dengesiz bir teklifiniz varsa bazen yararlıdır.
Bash'teki ' -x' seçeneğinin diğer kabuklardan farklı olduğu konusunda tartışmalar var (yorumlara bakın). Bash Kılavuzu diyor ki:
-x
Genişletildikten ve yürütülmeden önce basit komutların, forkomutların, casekomutların, selectkomutların ve aritmetik forkomutların ve bunların bağımsız değişkenlerinin veya ilişkili sözcük listelerinin bir izini yazdırın . Değeri PS4değişken genişletilir ve elde edilen değer komut ve genişletilmiş bağımsız değişkenler önce basılır.
Bu kadar çok farklı davranışlar göstermiyor gibi görünüyor. -xKılavuzda ' ' ile ilgili başka referans görmüyorum . Başlangıç dizisindeki farklılıkları tanımlamaz.
Açıklama : Tipik bir Linux kutusu gibi ' /bin/sh' için bir sembolik bağlantı olan ' /bin/bash' sistemlerde (veya Bash yürütülebilir dosyasının bulunduğu her yerde), iki komut satırı komut dosyasını yürütme izlemesiyle çalıştırmanın eşdeğer etkisini elde eder. Diğer sistemlerde (örneğin, Solaris ve Linux'un bazı daha modern varyantları) /bin/shBash değildir ve iki komut satırı (biraz) farklı sonuçlar verir. En önemlisi, ' /bin/sh' Bash'teki hiç tanımadığı yapılar tarafından karıştırılacaktı. (Solaris'te /bin/shBourne kabuğudur; modern Linux'ta bazen Dash - daha küçük, daha kesin olarak POSIX'e özgü bir kabuk.) Bu adla çağrıldığında 'shebang' hattı (' #!/bin/bash' vs '#!/bin/sh'
Bash kılavuzunda, Bash POSIX modunda , bu cevabın uzun süredir devam eden ancak hatalı bir versiyonunun aksine (aşağıdaki yorumlara da bakınız), 'Bash as invoke sh' ve 'Bash as invoke' arasındaki fark ayrıntılı olarak açıklanmaktadır. bash'.
(Bash) kabuk betiğinin hatalarını ayıklarken, -xseçenekle birlikte shebang satırında adlandırılan kabuğu kullanmak mantıklı ve akılcı olacaktır . Aksi takdirde, komut dosyasını çalıştırırken hata ayıklama sırasında farklı davranışlar elde edebilirsiniz (?).
bashsenaryo belirledi. Ve bir bash betiği çalıştırmak sh -xtamamen farklı davranmasına neden olur! Lütfen cevabınızı güncelleyin.
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
Senaryomda hata ayıklamak için aşağıdaki yöntemleri kullandım.
set -eherhangi bir harici program sıfırdan farklı bir çıkış durumu döndürürse komut dosyasını hemen durdurur. Komut dosyanız tüm hata durumlarını ele almaya çalışırsa ve bunu yapamamanız durumunda yararlıdır.
set -x yukarıda zikredilmiştir ve tüm hata ayıklama yöntemlerinden en faydalı olanıdır.
set -n betiğinizi sözdizimi hataları için kontrol etmek istiyorsanız da yararlı olabilir.
straceneler olduğunu görmek için de yararlıdır. Özellikle senaryoyu kendiniz yazmadıysanız yararlıdır.
strace -fAyrıca komut dosyası tarafından başlatılan süreçlerde hataları bulmak istiyorsanız gereklidir. (bu onu çok daha ayrıntılı hale getirir, ancak ilgilendiğiniz sistem çağrılarıyla sınırlarsanız yine de yararlıdır).
set -e... tartışmalı .
Bu cevap geçerli ve yararlı: https://stackoverflow.com/a/951352
Ancak, "standart" kod hata ayıklama yöntemlerinin verimsiz, sezgisel ve kullanımı zor olduğunu düşünüyorum. Her şeyi parmaklarınızın ucuna getiren ve işi kolay problemler (ve zor problemler için) için bir esinti yapan sofistike GUI hata ayıklayıcılarına alışkın olanlar için, bu çözümler çok tatmin edici değildir.
Yaptığım şey DDD ve bashdb'nin bir kombinasyonunu kullanmak. Birincisi ikincisini yürütür ve ikincisi komut dosyanızı yürütür. Bu, bağlamı kafanızda tutmak veya kaynağı yeniden listelemeye devam etmek için sürekli zihinsel çaba sarf etmeden bağlamda kod içinde adım atma ve değişkenleri, yığını vb. Görüntüleme yeteneğine sahip çok pencereli bir kullanıcı arayüzü sağlar.
Burada ayarlama konusunda rehberlik vardır: http://ubuntuforums.org/showthread.php?t=660223
Ayrıca komut dosyasına "set -x" yazabilirsiniz.
Shellcheck yardımcı programını buldum ve bazı insanlar ilginç bulabilirler https://github.com/koalaman/shellcheck
Küçük bir örnek:
$ cat test.sh
ARRAY=("hello there" world)
for x in $ARRAY; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in $ARRAY; do
^-- SC2128: Expanding an array without an index only gives the first element.
hatayı düzeltin, önce deneyin ...
$ cat test.sh
ARRAY=("hello there" world)
for x in ${ARRAY[@]}; do
echo $x
done
$ shellcheck test.sh
In test.sh line 3:
for x in ${ARRAY[@]}; do
^-- SC2068: Double quote array expansions, otherwise they're like $* and break on spaces.
Tekrar deneyelim...
$ cat test.sh
ARRAY=("hello there" world)
for x in "${ARRAY[@]}"; do
echo $x
done
$ shellcheck test.sh
şimdi bul!
Bu sadece küçük bir örnek.
Eklentileri kabuklu ve basheclipse ile kullanın.
https://sourceforge.net/projects/shelled/?source=directory https://sourceforge.net/projects/basheclipse/?source=directory
Kabuklu için: Zip dosyasını indirin ve yardım yoluyla eclipse'a aktarın -> yeni yazılım yükleyin: yerel arşiv Bashliplip için: Kavanozları eclipse'nin dropins dizinine kopyalayın
Https://sourceforge.net/projects/basheclipse/files/?source=navbar sağlayan adımları izleyin
Http://dietrichschroff.blogspot.de/2017/07/bash-enabling-eclipse-for-bash.html adresinde birçok ekran görüntüsü içeren bir eğitici yazdım.
Bir Bash hata ayıklayıcısı oluşturdum. Sadece bir deneyin. Umarım https://sourceforge.net/projects/bashdebugingbash yardımcı olur
set + x = @ECHO OFF, -x = @ECHO ON olarak ayarlayın.
-xvStandart Shebang'a aşağıdaki gibi seçenek ekleyebilirsiniz :
#!/bin/bash -xv
-x: Komutları ve bağımsız değişkenlerini yürütüldükleri sırada görüntüler.
-v: Kabuk giriş satırlarını okundukları gibi görüntüler.
ltracebenzeri başka bir Linux Yardımcı Programıdır strace. Ancak, ltraceyürütülebilir veya çalışan bir işlemde çağrılan tüm kütüphane çağrılarını listeler. Adının kendisi kütüphane çağrısı izlemesinden gelir. Örneğin:
ltrace ./executable <parameters>
ltrace -p <PID>
Bence bu Bash hata ayıklayıcısını deneyebilirsiniz: http://bashdb.sourceforge.net/ .
set -[nvx]Ek olarak
set -x
ve
set +x
dökümü durdurmak için.
Daha set -vaz gelişmiş çıktı kadar küçük dökümü hakkında konuşmak istiyorum .
bash <<<$'set -x\nfor i in {0..9};do\n\techo $i\n\tdone\nset +x' 2>&1 >/dev/null|wc -l
21
for arg in x v n nx nv nvx;do echo "- opts: $arg"
bash 2> >(wc -l|sed s/^/stderr:/) > >(wc -l|sed s/^/stdout:/) <<eof
set -$arg
for i in {0..9};do
echo $i
done
set +$arg
echo Done.
eof
sleep .02
done
- opts: x
stdout:11
stderr:21
- opts: v
stdout:11
stderr:4
- opts: n
stdout:0
stderr:0
- opts: nx
stdout:0
stderr:0
- opts: nv
stdout:0
stderr:5
- opts: nvx
stdout:0
stderr:5
Bazı değişkenleri test etmek için bazen şunu kullanıyorum:
bash <(sed '18ideclare >&2 -p var1 var2' myscript.sh) args
Eklemek için:
declare >&2 -p var1 var2
satır 18'de ve ortaya çıkan komut dosyasını ( argümanlarla ) çalıştırmak zorunda kalmadan, bunları düzenlemek zorunda kalmadan.
tabii ki, bu eklemek için kullanılabilir set [+-][nvx]:
bash <(sed '18s/$/\ndeclare -p v1 v2 >\&2/;22s/^/set -x\n/;26s/^/set +x\n/' myscript) args
declare -p v1 v2 >&2satır 18'den sonra, set -xsatır 22'den set +xönce ve satır 26'dan önce eklenecektir .
bash <(sed '2,3s/$/\ndeclare -p LINENO i v2 >\&2/;5s/^/set -x\n/;7s/^/set +x\n/' <(
seq -f 'echo $@, $((i=%g))' 1 8)) arg1 arg2
arg1 arg2, 1
arg1 arg2, 2
declare -i LINENO="3"
declare -- i="2"
/dev/fd/63: line 3: declare: v2: not found
arg1 arg2, 3
declare -i LINENO="5"
declare -- i="3"
/dev/fd/63: line 5: declare: v2: not found
arg1 arg2, 4
+ echo arg1 arg2, 5
arg1 arg2, 5
+ echo arg1 arg2, 6
arg1 arg2, 6
+ set +x
arg1 arg2, 7
arg1 arg2, 8
Not: Dikkat , anında yapılan değişikliklerden $LINENOetkilenecektir !
(Çalıştırılmadan ortaya çıkan komut dosyasını görmek için, bırakın bash <(ve bırakın ) arg1 arg2)
Bash betiklerini nasıl profili oluşturacağımla ilgili cevabıma bir göz atın
Kabuk betikleri için küresel kabuk değişkenleri üzerinden günlük kaydı konusunda iyi ayrıntılar vardır. Kabuk betiğinde benzer günlük kaydını taklit edebiliriz: http://www.cubicrace.com/2016/03/log-tracing-mechnism-for-shell-scripts.html
Gönderi, INFO, DEBUG, ERROR gibi introdducing log seviyeleri hakkında ayrıntılara sahiptir. Kod girişi, kod çıkışı, işlev girişi, işlev çıkışı gibi izleme ayrıntıları.
Örnek günlük: