Kabuk komutları yürütüldükçe nasıl yankılanır


911

Bir kabuk komut dosyasında, çağrılan tüm kabuk komutlarını yankılayabilir ve değişken adlarını nasıl genişletebilirim?

Örneğin, aşağıdaki satır verildiğinde:

ls $DIRNAME

Komut dosyasını komutu çalıştırmak ve aşağıdakileri görüntülemek istiyorum

ls /full/path/to/some/dir

Amaç, çağrılan tüm kabuk komutlarının ve argümanlarının bir kaydını saklamaktır. Böyle bir kütük oluşturmanın belki de daha iyi bir yolu var mı?

Yanıtlar:


1042

set -xveya set -o xtracedeğişkenleri genişletir ve çizgiden önce küçük bir + işareti yazdırır.

set -vveya set -o verboseyazdırmadan önce değişkenleri genişletmez.

Yukarıdaki ayarları kapatmak için set +xve tuşlarını kullanın set +v.

Senaryonun ilk satırında, tek koyabilirsiniz #!/bin/sh -x(veya -vaynı şekilde etkilenmemek için) set -x(veya -vdaha sonraki komut).

Yukarıdakiler de ile çalışır /bin/sh.

setÖznitelikler ve hata ayıklama ile ilgili bash hackerların wiki'sine bakın .

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

$ bash -x shl 
+ DIR=/tmp/so
+ ls /tmp/so
$

7
Ayrıca hangi numaralı hattın yürütüldüğünü görmek istiyorsanız bkz. Stackoverflow.com/a/17805088/1729501
user13107

3
Komutu ve sonuç çıktısını ayırt etmek için yankılanırken komutu renklendirmek istersem ne olur?
Lewis Chan

10
Yankılanırken her bir komutu vocaloid benzeri bir konuşma sentezleyicisi aracılığıyla söylemesini istersem, böylece uzaktan ne yaptığını duyabilir ve müziğin keyfini çıkarabilirim? Belki de girişler ve çıkışlar için farklı bir sesle.
ADJenks

(ABS'nin, kötü uygulama örneklerini düzelterek, uzun süredir devam eden topluluk üyelerini rakip kaynaklar yaratmaya itme noktasına yanıt vermeme konusunda uzun bir geçmişi vardır; bağlantıları bash hackerların wiki'sine - Wooledge wiki veya resmi bash el kitabı da daha iyi kaynaklar olacaktır).
Charles Duffy

317

set -x istediğini verecek.

Göstermek için örnek bir kabuk betiği:

#!/bin/bash
set -x #echo on

ls $PWD

Bu, tüm değişkenleri genişletir ve komutun çıkışından önce tam komutları yazdırır.

Çıktı:

+ ls /home/user/
file1.txt file2.txt

21
"Ayrıntılı" kelimesini bu şekilde kullanmak hiçbir şey başaramaz. Sen yapabilir set -o verboseveya set -v(sadece "Ayrıntılı") veya set -o xtraceveya set -x(sadece "XTrace") veya set -xv(her ikisi) veya set -o xtrace -o verbose(her ikisi).
sonraki duyuruya kadar duraklatıldı.

Bu iyi çalışıyor, ancak "ayrıntılı" 1 $ üzerine yazıldığını unutmayın
JasonS

90

Yankı ve komutu çalıştırmak için bir işlev kullanın:

#!/bin/bash
# Function to display commands
exe() { echo "\$ $@" ; "$@" ; }

exe echo hello world

Hangi çıktılar

$ echo hello world
hello world

Daha karmaşık komutlar boruları, vb için eval kullanabilirsiniz:

#!/bin/bash
# Function to display commands
exe() { echo "\$ ${@/eval/}" ; "$@" ; }

exe eval "echo 'Hello, World!' | cut -d ' ' -f1"

Hangi çıktılar

$  echo 'Hello, World!' | cut -d ' ' -f1
Hello

Bu cevap için çok oy yok. Kötü bir fikir olmasının bir nedeni var mı? Benim için çalıştı ve tam olarak aradığım şey gibi görünüyor ...
fru1tbat

1
Her komutun yazdırılmasını istemiyorsanız en iyi yanıt budur. Kapatıldığında ++ set +xçıktıyı temizler ve daha temiz görünür. Bununla birlikte, sadece bir veya iki açıklama için, bhassel'in bir alt kabuk kullanarak verdiği cevap en uygun olanıdır.
Brent Faust

Aradığım şey bu! Hayır set +x, çok fazla olan tüm komutları etkiler!
Hlung

11
Bunun önemli bir dezavantajı, çıktının teklif bilgilerini kaybetmesidir. Örneğin cp "foo bar" bazve arasında ayrım yapamazsınız cp foo "bar baz". Bu nedenle, bir kullanıcıya ilerleme bilgilerinin gösterilmesi iyidir; çıktıda hata ayıklamak veya tekrarlanabilir komutları kaydetmek için daha az. Farklı kullanım durumları. İçinde zsh, :qdeğiştirici ile alıntı koruyabilirsiniz :exe() { echo '$' "${@:q}" ; "$@" ; }
Andrew Janke

2
Bu cevabı sevmiyorum. Gördüğünüz şeyin aldığınız şey olmadığı birçok kenar durumu vardır (özellikle boşluk, tırnak işaretleri, kaçan karakterler, değişken / ifade yerine koyma vb.), Bu nedenle echoed komutunu bir terminale körü körüne yapıştırmayın ve çalışacağını varsayın aynı yol. Ayrıca, ikinci teknik sadece bir hack'tir ve kelimenin diğer örneklerini evalkomutunuzdan çıkarır . Bu yüzden düzgün çalışmasını beklemeyin exe eval "echo 'eval world'"!
mwfearnley

88

Ayrıca, betiğinizdeki belirli satırları içine alarak bunları değiştirebilir set -xve set +xörneğin,

#!/bin/bash
...
if [[ ! -e $OUT_FILE ]];
then
   echo "grabbing $URL"
   set -x
   curl --fail --noproxy $SERV -s -S $URL -o $OUT_FILE
   set +x
fi

54

shuckc'nin seçme satırlarını yankılama cevabının birkaç dezavantajı vardır: aşağıdaki set +xkomutun da yankılanmasıyla sonuçlanırsınız ve $?tarafından yazıldığı için çıkış kodunu test etme yeteneğini kaybedersiniz set +x.

Başka bir seçenek, komutu bir alt kabukta çalıştırmaktır:

echo "getting URL..."
( set -x ; curl -s --fail $URL -o $OUTFILE )

if [ $? -eq 0 ] ; then
    echo "curl failed"
    exit 1
fi

hangi size çıktı verecektir gibi:

getting URL...
+ curl -s --fail http://example.com/missing -o /tmp/example
curl failed

Bu, komut için yeni bir alt kabuk oluşturma yükünü beraberinde getirir.


7
++ set +xÇıkışı önlemek için güzel bir yol .
Brent Faust

3
Daha da iyisi: yerine if [ $? -eq 0 ]ile if (set -x; COMMAND).
Amedee Van Gasse

35

Başka bir seçenek de komut satırınızın üstüne komut satırı yerine "-x" koymaktır:

$ cat ./server
#!/bin/bash -x
ssh user@server

$ ./server
+ ssh user@server
user@server's password: ^C
$

Bunun ./myScriptve ile tam olarak aynı işe yaramadığını unutmayın bash myScript. Yine de belirtmek için iyi bir şey, teşekkürler.
altendky

27

Göre TLDP 'ın Bölüm 2. Yazma ve hata ayıklama komut: Yeni Başlayanlar için Bash Rehberi :

2.3.1. Komut dosyasının tamamında hata ayıklama

$ bash -x script1.sh

...

Artık Bash için SourceForge'da kullanılabilen tam teşekküllü bir hata ayıklayıcı var . Bu hata ayıklama özellikleri, 3.x'ten başlayarak Bash'in modern sürümlerinin çoğunda mevcuttur.

2.3.2. Komut dosyasının bazı bölümlerinde hata ayıklama

set -x            # Activate debugging from here
w
set +x            # Stop debugging from here

...

Tablo 2-1. Hata ayıklama seçeneklerini ayarlama

    Short  | Long notation | Result
    -------+---------------+--------------------------------------------------------------
    set -f | set -o noglob | Disable file name generation using metacharacters (globbing).
    set -v | set -o verbose| Prints shell input lines as they are read.
    set -x | set -o xtrace | Print command traces before executing command.

...

Alternatif olarak, bu modlar, ilk satır kabuğu bildirimine istenen seçenekler eklenerek komut dosyasının kendisinde belirtilebilir. Seçenekler genellikle UNIX komutlarında olduğu gibi birleştirilebilir:

#!/bin/bash -xv

18

Bash komut dosyasının adından önce komut satırına "bash -x" yazın. Örneğin, foo.sh dosyasını çalıştırmak için şunu yazın:

bash -x foo.sh

11

Şunları yapabilirsiniz yürütmek ile hata ayıklama modunda bir Bash script -xseçeneği .

Bu, tüm komutları tekrarlayacaktır.

bash -x example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt

Ayrıca komut dosyasına -x seçeneğini de kaydedebilirsiniz . Sadece -xshebang seçeneği belirtin .

######## example_script.sh ###################
#!/bin/bash -x

cd /home/user
mv text.txt mytext.txt

##############################################

./example_script.sh

# Console output
+ cd /home/user
+ mv text.txt mytext.txt

2
Aynı bash -vxşeyi yapacak ama değişken enterpolasyon olmadan
loa_in_

4

Zsh, echo için

 setopt VERBOSE

Ve hata ayıklamak için,

 setopt XTRACE

2

İçin cshve tcshşunları yapabilirsiniz set verboseveya set echo(veya hatta her ikisi ayarlayabilirsiniz, ancak bazı çoğaltılması çoğu zaman neden olabilir).

verboseSeçenek yazdığınız o hemen hemen kesin kabuk ifadesini yazdırır.

echoSeçenek yumurtlama yoluyla icra edilecektir ne daha göstergesidir.


http://www.tcsh.org/tcsh.html/Special_shell_variables.html#verbose

http://www.tcsh.org/tcsh.html/Special_shell_variables.html#echo


Special shell variables

verbose If set, causes the words of each command to be printed, after history substitution (if any). Set by the -v command line option.

echo If set, each command with its arguments is echoed just before it is executed. For non-builtin commands all expansions occur before echoing. Builtin commands are echoed before command and filename substitution, because these substitutions are then done selectively. Set by the -x command line option.


1
$ cat exampleScript.sh
#!/bin/bash
name="karthik";
echo $name;

bash -x exampleScript.sh

Çıktı aşağıdaki gibidir:

resim açıklamasını buraya girin


Terminalinizin renk tanımları nelerdir (RGB, sayısal)?
Peter Mortensen

1

Bileşik komutların yankılanmasına izin vermek için , komutu yankılayıp çalıştırmak için evalartı Soth exeişlevini kullanıyorum. Bu, piped komutunun yalnızca hiçbirini veya yalnızca ilk kısmını göstermeyen borulu komutlar için kullanışlıdır.

Eval olmadan:

exe() { echo "\$ $@" ; "$@" ; }
exe ls -F | grep *.txt

Çıktılar:

$
file.txt

Eval ile:

exe() { echo "\$ $@" ; "$@" ; }
exe eval 'ls -F | grep *.txt'

Hangi çıktılar

$ exe eval 'ls -F | grep *.txt'
file.txt
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.