Jak echo poleceń powłoki podczas ich wykonywania

910

W skrypcie powłoki, w jaki sposób mogę wywołać echo wszystkich wywoływanych poleceń powłoki i rozwinąć nazwy zmiennych?

Na przykład, biorąc pod uwagę następujący wiersz:

ls $DIRNAME

Chciałbym, aby skrypt uruchomił polecenie i wyświetlił następujące informacje

ls /full/path/to/some/dir

Celem jest zapisanie dziennika wszystkich wywoływanych poleceń powłoki i ich argumentów. Czy jest może lepszy sposób na wygenerowanie takiego dziennika?

Jack Nock
źródło

Odpowiedzi:

1041

set -xlub set -o xtracerozwija zmienne i wypisuje mały znak + przed linią.

set -vlub set -o verbosenie rozwija zmiennych przed drukowaniem.

Użyj set +xi, set +vaby wyłączyć powyższe ustawienia.

W pierwszym wierszu skryptu można umieścić #!/bin/sh -x(lub -v), aby uzyskać taki sam efekt jak set -x(lub -v) później w skrypcie.

Powyższe działa również z /bin/sh.

Zobacz wiki bash-hackerów na temat setatrybutów i debugowania .

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

$ bash -x shl 
+ DIR=/tmp/so
+ ls /tmp/so
$
Tomek
źródło
7
Jeśli chcesz również sprawdzić, która linia numerowana jest wykonywana, zobacz stackoverflow.com/a/17805088/1729501
użytkownik13107
3
co jeśli chcę pokolorować polecenie podczas echa w celu rozróżnienia polecenia i jego wyników?
Lewis Chan,
10
Co jeśli chcę, aby śpiewało każde polecenie za pomocą syntezatora mowy podobnego do wokalu podczas echa, aby słyszeć, co robi z daleka, a także cieszyć się muzyką? Być może innym głosem dla wejść i wyjść.
ADJenks
(ABS od dawna nie reaguje na prośby o skorygowanie przykładów złych praktyk, do tego stopnia, że ​​nakłania długoletnich członków społeczności do tworzenia konkurencyjnych zasobów; przeniósł linki do wiki bash-hakerów - wiki Wooledge lub oficjalna instrukcja bash byłaby również lepszymi zasobami).
Charles Duffy,
316

set -x da ci to, czego chcesz.

Oto przykładowy skrypt powłoki do zademonstrowania:

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

ls $PWD

Rozwija wszystkie zmienne i wypisuje pełne polecenia przed wyjściem polecenia.

Wynik:

+ ls /home/user/
file1.txt file2.txt
radman
źródło
21
Używanie w ten sposób słowa „gadatliwy” niczego nie osiąga. Możesz zrobić set -o verboselub set -v(tylko „pełne”) lub set -o xtracelub set -x(tylko „xtrace”) lub set -xv(oba) lub set -o xtrace -o verbose(oba).
Wstrzymano do odwołania.
to działa dobrze, ale należy pamiętać, że „pełne
słowo
90

Korzystam z funkcji, aby wywołać echo i uruchomić polecenie:

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

exe echo hello world

Które wyjścia

$ echo hello world
hello world

W przypadku bardziej skomplikowanych potoków poleceń, możesz użyć eval:

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

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

Które wyjścia

$  echo 'Hello, World!' | cut -d ' ' -f1
Hello
Soth
źródło
Niewiele głosów za tą odpowiedzią. Czy istnieje powód, dla którego jest to zły pomysł? Pracował dla mnie i wydaje się być dokładnie tym, czego szukam ...
fru1tbat
1
To najlepsza odpowiedź, jeśli nie chcesz drukować każdego polecenia. Unika ++ set +xwyjścia, gdy jest wyłączony, a także wygląda bardziej czysto. Jednak w przypadku pojedynczej instrukcji lub dwóch odpowiedź bhassel przy użyciu podpowłoki jest najwygodniejsza.
Brent Faust
Właśnie tego szukam! Nie set +x, wpływa to na wszystkie polecenia, co jest zbyt wiele!
Hlung
11
Główną wadą tego jest to, że wynik traci informacje o cytowaniu. Nie można na przykład rozróżniać między cp "foo bar" bazi cp foo "bar baz". Jest więc dobry do wyświetlania użytkownikowi informacji o postępach; w mniejszym stopniu do debugowania danych wyjściowych lub nagrywania powtarzalnych poleceń. Różne przypadki użycia. W zsh, można zachować cytowanie z :qmodyfikatora:exe() { echo '$' "${@:q}" ; "$@" ; }
Andrew Janke
2
Nie podoba mi się ta odpowiedź. Istnieje wiele przypadków krawędzi, w których to, co widzisz, nie jest tym, co dostajesz (szczególnie z białymi znakami, cudzysłowami, znakami zmiany znaczenia, zamianami zmiennych / wyrażeń itp.), Więc nie wklejaj ślepo echa polecenia do terminala i zakładaj, że zadziała w ten sam sposób. Ponadto, druga technika to tylko hack i usunie inne wystąpienia tego słowa evalz twojego polecenia. Więc nie oczekuj, że będzie działać poprawnie exe eval "echo 'eval world'"!
mwfearnley
88

Możesz także przełączać to dla wybranych linii w skrypcie, zawijając je set -xi set +xna przykład

#!/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
shuckc
źródło
54

Odpowiedź shuckc na echo wybranych linii ma kilka wad: kończy się także set +xecho następującej komendy i tracisz możliwość testowania kodu wyjścia, $?ponieważ zostaje on nadpisany przez set +x.

Inną opcją jest uruchomienie polecenia w podpowłoce:

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

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

co da ci wynik jak:

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

Powoduje to jednak obciążenie związane z tworzeniem nowej podpowłoki dla polecenia.

Bhassel
źródło
7
Miły sposób na uniknięcie ++ set +xwyjścia.
Brent Faust,
3
Nawet lepiej zamienić if [ $? -eq 0 ]z if (set -x; COMMAND).
Amedee Van Gasse
35

Inną opcją jest umieszczenie „-x” na górze skryptu zamiast w wierszu poleceń:

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

$ ./server
+ ssh user@server
user@server's password: ^C
$
nooj
źródło
Zauważ, że to nie wydaje się działać dokładnie tak samo między ./myScripti bash myScript. Wciąż warto zwrócić uwagę, dzięki.
altendky
27

Według tldp „s Bash Przewodnik dla początkujących: Rozdział 2. Pisanie skryptów i debugowania :

2.3.1 Debugowanie całego skryptu

$ bash -x script1.sh

...

Istnieje teraz pełnoprawny debugger dla Bash, dostępny na SourceForge . Te funkcje debugowania są dostępne w najnowocześniejszych wersjach Bash, począwszy od wersji 3.x.

2.3.2 Debugowanie części skryptu

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

...

Tabela 2-1. Przegląd ustawionych opcji debugowania

    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.

...

Alternatywnie tryby te można określić w samym skrypcie, dodając żądane opcje do deklaracji powłoki w pierwszym wierszu. Opcje można łączyć, jak zwykle w przypadku komend UNIX:

#!/bin/bash -xv
Afriza N. Arief
źródło
18

Wpisz „bash -x” w wierszu poleceń przed nazwą skryptu Bash. Na przykład, aby uruchomić foo.sh, wpisz:

bash -x foo.sh
Alan
źródło
11

Możesz wykonać skrypt Bash w trybie debugowania z -xopcją .

Spowoduje to echo wszystkich poleceń.

bash -x example_script.sh

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

Możesz także zapisać opcję -x w skrypcie . Po prostu określ -xopcję w shebang.

######## 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
RenRen
źródło
2
Też bash -vxzrobi to samo, ale bez zmiennej interpolacji
loa_in_
4

Dla Zsh, echo

 setopt VERBOSE

I do debugowania

 setopt XTRACE
zzapper
źródło
2

Dla cshi tcsh, możesz set verboselub set echo(lub możesz nawet ustawić oba, ale może to prowadzić do pewnego powielania przez większość czasu).

Ta verboseopcja drukuje prawie dokładnie to, co wpisujesz.

Ta echoopcja bardziej wskazuje na to, co zostanie wykonane przez spawnowanie.


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.

cnst
źródło
1
$ cat exampleScript.sh
#!/bin/bash
name="karthik";
echo $name;

bash -x exampleScript.sh

Dane wyjściowe są następujące:

wprowadź opis zdjęcia tutaj

Karthik Arun
źródło
Jakie są definicje kolorów dla twojego terminala (RGB, numerycznie)?
Peter Mortensen
1

Aby umożliwić echo poleceń złożonych, używam funkcji evalplus Sotha, aby wywołać exeecho i uruchomić polecenie. Jest to przydatne w przypadku poleceń potokowych, które w innym przypadku nie pokazałyby tylko żadnej lub tylko początkowej części polecenia potokowego.

Bez oceny:

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

Wyjścia:

$
file.txt

Z eval:

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

Które wyjścia

$ exe eval 'ls -F | grep *.txt'
file.txt
Paul Havens
źródło