Come eseguire l'eco dei comandi della shell mentre vengono eseguiti


912

In uno script di shell, come faccio a ripetere tutti i comandi di shell chiamati ed espandere i nomi delle variabili?

Ad esempio, data la seguente riga:

ls $DIRNAME

Vorrei che lo script eseguisse il comando e visualizzasse quanto segue

ls /full/path/to/some/dir

Lo scopo è quello di salvare un registro di tutti i comandi shell chiamati e dei loro argomenti. Esiste forse un modo migliore per generare un tale registro?

Risposte:


1043

set -xo set -o xtraceespande le variabili e stampa un piccolo segno + prima della riga.

set -vo set -o verbosenon espande le variabili prima della stampa.

Utilizzare set +xe set +vper disattivare le impostazioni sopra.

Sulla prima riga dello script, si può mettere #!/bin/sh -x(o -v) per avere lo stesso effetto di set -x(o -v) successivamente nello script.

Quanto sopra funziona anche con /bin/sh.

Vedi il wiki di bash-hacker sugli setattributi e sul debug .

$ cat shl
#!/bin/bash                                                                     

DIR=/tmp/so
ls $DIR

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

7
Se anche voi volete vedere quale numerata linea viene eseguito See stackoverflow.com/a/17805088/1729501
user13107

3
cosa succede se desidero colorare il comando durante l'eco per differenziare il comando e l'output dei risultati?
Lewis Chan,

11
E se volessi che cantasse ogni comando attraverso un sintetizzatore vocale simile a vocaloid durante l'eco, così posso sentire cosa sta facendo da lontano e anche ascoltare la musica? Forse con una voce diversa per ingressi e uscite.
ADJenks,

(L'ABS ha una lunga storia di mancata risposta alle richieste di correzione di esempi di cattive pratiche, al punto di spingere i membri della comunità di lunga data a creare risorse concorrenti; spostato i collegamenti al wiki degli hacker di base - il wiki Wooledge o il il manuale ufficiale di bash sarebbe anche una risorsa migliore).
Charles Duffy,

317

set -x ti darà quello che vuoi.

Ecco un esempio di script di shell per dimostrare:

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

ls $PWD

Questo espande tutte le variabili e stampa i comandi completi prima dell'output del comando.

Produzione:

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

21
Usando la parola "verbose" in quel modo non si ottiene nulla. Puoi fare set -o verboseo set -v(solo "verbose") o set -o xtraceo set -x(solo "xtrace") o set -xv(entrambi) o set -o xtrace -o verbose(entrambi).
In pausa fino a nuovo avviso.

questo funziona bene, ma
tieni

90

Uso una funzione per eseguire l'eco ed eseguire il comando:

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

exe echo hello world

Quali uscite

$ echo hello world
hello world

Per comandi più complicati, pipe, ecc., Puoi usare eval:

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

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

Quali uscite

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

Non molti voti per questa risposta. C'è una ragione per cui è una cattiva idea? Ha funzionato per me e sembra essere esattamente quello che sto cercando ...
fru1tbat

1
Questa è la risposta migliore se non si desidera stampare tutti i comandi. Evita l' ++ set +xuscita quando è spento, oltre a sembrare più pulito. Per una sola o due affermazioni, tuttavia, la risposta di bhassel usando una subshell è la più conveniente.
Brent Faust,

Questo è quello che sto cercando! No set +x, influenza tutti i comandi, il che è troppo!
Hlung,

11
Un aspetto negativo di questo è che l'output perde le informazioni di quotazione. Non è possibile distinguere tra cp "foo bar" baze cp foo "bar baz", ad esempio. Quindi è utile per visualizzare informazioni sullo stato di avanzamento per un utente; meno per il debug dell'output o la registrazione di comandi riproducibili. Diversi casi d'uso. In zsh, puoi conservare le citazioni con il :qmodificatore:exe() { echo '$' "${@:q}" ; "$@" ; }
Andrew Janke,

2
Non mi piace questa risposta. Ci sono molti casi limite in cui ciò che vedi non è ciò che ottieni (specialmente con spazi bianchi, virgolette, caratteri di escape, sostituzioni di variabili / espressioni, ecc.), Quindi non incollare ciecamente il comando echoed in un terminale e supporre che verrà eseguito allo stesso modo. Inoltre, la seconda tecnica è solo un hack e toglierà altre istanze della parola evaldal tuo comando. Quindi non aspettarti che funzioni correttamente exe eval "echo 'eval world'"!
mwfearnley,

88

Puoi anche attivare questa opzione per selezionare le righe nello script avvolgendole set -xe set +x, ad esempio,

#!/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

La risposta di shuckc per l'eco delle linee selezionate ha alcuni aspetti negativi: si finisce con l' set +xeco del seguente comando e si perde la possibilità di testare il codice di uscita $?poiché viene sovrascritto da set +x.

Un'altra opzione è eseguire il comando in una subshell:

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

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

che ti darà un output come:

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

Ciò comporta però il sovraccarico di creare una nuova subshell per il comando.


7
Bel modo di evitare l' ++ set +xoutput.
Brent Faust,

3
Ancora meglio: sostituirlo if [ $? -eq 0 ]con if (set -x; COMMAND).
Amedee Van Gasse,

35

Un'altra opzione è quella di mettere "-x" nella parte superiore dello script anziché nella riga di comando:

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

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

Si noti che questo non sembra funzionare esattamente allo stesso modo tra ./myScripte bash myScript. Ancora una buona cosa da sottolineare, grazie.
altendky,

27

Secondo la Bash Guide di TLDP per principianti: Capitolo 2. Scrittura e debug di script :

2.3.1. Debug sull'intero script

$ bash -x script1.sh

...

Ora esiste un debugger completo per Bash, disponibile su SourceForge . Queste funzionalità di debug sono disponibili nella maggior parte delle versioni moderne di Bash, a partire dalla 3.x.

2.3.2. Debug su parti del copione

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

...

Tabella 2-1 Panoramica delle opzioni di debug impostate

    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.

...

In alternativa, queste modalità possono essere specificate nello script stesso, aggiungendo le opzioni desiderate alla dichiarazione della shell della prima riga. Le opzioni possono essere combinate, come di solito accade con i comandi UNIX:

#!/bin/bash -xv

18

Digita "bash -x" sulla riga di comando prima del nome dello script Bash. Ad esempio, per eseguire foo.sh, digitare:

bash -x foo.sh

11

È possibile eseguire uno script Bash in modalità debug con l' -xopzione .

Questo farà eco a tutti i comandi.

bash -x example_script.sh

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

Puoi anche salvare l'opzione -x nello script . Basta specificare l' -xopzione nello 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

2
Inoltre bash -vxfarà lo stesso, ma senza interpolazione variabile
loa_in_

4

Per zsh, eco

 setopt VERBOSE

E per il debug,

 setopt XTRACE

2

Per cshe tcsh, puoi set verboseoset echo (o puoi anche impostare entrambi, ma il risultato potrebbe essere la duplicazione per la maggior parte del tempo).

Il verbose opzione stampa praticamente l'espressione shell che si digita.

L' echoopzione è più indicativa di ciò che verrà eseguito attraverso la deposizione delle uova.


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

L'output è il seguente:

inserisci qui la descrizione dell'immagine


Quali sono le definizioni di colore per il tuo terminale (RGB, numerico)?
Peter Mortensen,

1

Per consentire l'eco dei comandi composti, uso evalla exefunzione plus Soth per eseguire l'eco ed eseguire il comando. Ciò è utile per i comandi piped che altrimenti mostrerebbero nessuno o solo la parte iniziale del comando piped.

Senza valutazione:

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

Uscite:

$
file.txt

Con eval:

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

Quali uscite

$ exe eval 'ls -F | grep *.txt'
file.txt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.