Come eseguire il debug di uno script bash?


135

Sto riscontrando alcuni problemi con alcuni script in bash, su errori e comportamenti imprevisti. Vorrei indagare sulle cause dei problemi in modo da poter applicare correzioni. C'è un modo in cui posso trasformare una sorta di "modalità debug" per bash, per ottenere maggiori informazioni?

Risposte:


132

Inizia il tuo script bash con bash -x ./script.sho aggiungi il tuo script set -xper vedere l'output di debug.


Aggiuntivo con bash4.1 o successivo:

Se vuoi scrivere l'output di debug in un file separato, aggiungi questo al tuo script:

exec 5> debug_output.txt
BASH_XTRACEFD="5"

Vedi: https://stackoverflow.com/a/25593226/3776858


Se vuoi vedere i numeri di riga aggiungi questo:

PS4='$LINENO: '


Se hai accesso al loggercomando, puoi usarlo per scrivere l'output di debug tramite il tuo syslog con timestamp, nome dello script e numero di riga:

#!/bin/bash

exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
PS4='$LINENO: '
set -x

# Place your code here

È possibile utilizzare l'opzione -pdi loggercomando per impostare una singola funzione e livello per scrivere l'output tramite syslog locale nel proprio file di registro.


7
-v può anche aiutare (stampa ogni riga man mano che vengono eseguite. può essere combinata con -x). E vedi anche: bashdb.sourceforge.net
Olivier Dulac il

4
un'altra meravigliosa risorsa è: shellcheck.net
Olivier Dulac

Che cosa fa "exec 5>"?
aggsol,

3
@aggsol: se si utilizza BASH_XTRACEFD="5"bash scrive l'output di traccia generato quando set -xè abilitato al descrittore di file 5. exec 5> >(logger -t $0)reindirizza l'output dal descrittore di file 5 al loggercomando.
Ciro,

1
Ti stai solo chiedendo come ottenere il numero di riga e il percorso o il nome dello script della shell in PS4?
iloveretards,

55

utilizzando set -x

Uso sempre set -xe set +x. Puoi avvolgere le aree in cui vuoi vedere cosa sta succedendo con loro per aumentare / diminuire la verbosità.

#!/bin/bash

set -x
..code to debug...
set +x

log4bash

Inoltre, se hai svolto un lavoro di sviluppo e hai familiarità con lo stile dei logger che vanno con i nomi log4j, log4perl, ecc., Allora potresti voler usare log4bash .

estratto

Ammettiamolo: il semplice vecchio eco non lo taglia. log4bash è un tentativo di avere una migliore registrazione per gli script Bash (cioè fare in modo che la registrazione in Bash risulti meno efficace).

Da lì puoi fare cose come queste nei tuoi script Bash:

#!/usr/bin/env bash
source log4bash.sh

log "This is regular log message... log and log_info do the same thing";

log_warning "Luke ... you turned off your targeting computer";
log_info "I have you now!";
log_success "You're all clear kid, now let's blow this thing and go home.";
log_error "One thing's for sure, we're all gonna be a lot thinner.";

# If you have figlet installed -- you'll see some big letters on the screen!
log_captains "What was in the captain's toilet?";

# If you have the "say" command (e.g. on a Mac)
log_speak "Resistance is futile";

Risultato in questo tipo di output:

    ss1

log4sh

Se hai bisogno di qualcosa di più portatile c'è anche il più vecchio log4sh. Opere simili a log4bash, disponibili qui:


Su Ubuntu, ho alias say="spd-say"nel mio .bashrc, che imita il saycomando da altre distro o OS X.
Doorknob,

1
set -vx sarebbe una buona combinazione se usato con debug trap - trap read. Questo ti permette di scavalcare riga per riga e vedere i risultati
Magnus Melwin

34

C'è un debugger bash, bashdb , che è un pacchetto installabile su molte distribuzioni. Utilizza la modalità di debug estesa integrata di bash ( shopt -s extdebug). Assomiglia molto a gdb; ecco una sessione di esempio per dare un po 'di sapore:

$ ls
1st.JPG  2ndJPG.JPG
$ cat ../foo.sh
for f in *.JPG
do
  newf=${f/JPG/jpg}
  mv $f $newf
done
$ bashdb ../foo.sh
(foo.sh:1):
1:      for f in *.JPG
bashdb<0> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<1> next
(foo.sh:4):
4:        mv $f $newf

Come in gdb, l'istruzione viene mostrata poco prima che stia per essere eseguita. Quindi possiamo esaminare le variabili per vedere cosa farà l'istruzione prima di farlo.

bashdb<2> print $f $newf
1st.JPG 1st.jpg
bashdb<3> next
(foo.sh:1):
1:      for f in *.JPG
bashdb<4> next
(foo.sh:3):
3:        newf=${f/JPG/jpg}
bashdb<5> next
(foo.sh:4):
4:        mv $f $newf
bashdb<6> print $f $newf
2ndJPG.JPG 2ndjpg.JPG

Non è quello che vogliamo! Diamo un'occhiata di nuovo all'espansione dei parametri.

bashdb<7> print $f ${f/JPG/jpg}
2ndJPG.JPG 2ndjpg.JPG
bashdb<8> print $f ${f/JPG$/jpg}
2ndJPG.JPG 2ndJPG.JPG
bashdb<9> print $f ${f/%JPG/jpg}
2ndJPG.JPG 2ndJPG.jpg

OK, funziona. Impostiamo newfil valore corretto.

bashdb<10> eval newf=${f/%JPG/jpg}
$? is 0
bashdb<11> print $f $newf
2ndJPG.JPG 2ndJPG.jpg

Sembra buono. Continua la sceneggiatura.

bashdb<12> next
Debugged program terminated normally. Use q to quit or R to restart.
$ ls
1st.jpg  2ndJPG.jpg

20

Il metodo standard per il debug degli script nella maggior parte delle shell basate su Bourne, come bash, è scrivere set -xnella parte superiore dello script. Ciò renderà Bash più dettagliato su ciò che viene fatto / eseguito e su come vengono valutati gli argomenti.

-x  Print commands and their arguments as they are executed.

questo è utile sia per l'interprete che per gli script interni. Per esempio:

$ find "$fileloc" -type f -prune "$filename" -print
+ find /var/adm/logs/morelogs -type f -prune '-name *.user' -print
find: unknown predicate '-name *.user'
$ find "$fileloc" -type f -prune $filename -print
+ find /var/adm/logs/morelogs -type f -prune -name '*.user' -print
find: '/var/adm/logs/morelogs': No such file or directory

In quanto sopra possiamo vedere perché find sta fallendo a causa di alcune virgolette singole.

Per disattivare la funzione, basta digitare set +x.


13

Utilizzando Eclipse

È possibile utilizzare l'ambiente combinato di Eclipse e Shelled con lo script "_DEBUG.sh" collegato di seguito.

Cambio di shell

Per impostazione predefinita, lo strumento di sviluppo Shelled utilizza /bin/dashcome interprete. Ho cambiato questo per /bin/bashavere una migliore compatibilità con la maggior parte degli esempi di shell sul web e nel mio ambiente.

NOTA: è possibile modificarlo andando su: Finestra -> Preferenze -> Script shell -> Interpreti

Istruzioni per l'installazione

Il pacchetto Debugger prevede i passaggi per l'utilizzo dello _DEBUG.shscript per il debug degli script, che è sostanzialmente (readme.txt):

  1. Crea progetto script shell: File -> Nuovo -> Altro -> Script shell -> Procedura guidata progetto script shell .
  2. Crea un file di script Bash: File -> Nuovo -> File . Per questo esempio, lo sarà script.sh. L'estensione dovrebbe essere ".sh" ed è un must.
  3. Copia il file _DEBUG.shnella cartella del progetto.
  4. Inserisci il testo seguente nella parte superiore del file script.sh:

    . _DEBUG.sh
  5. Se il file viene creato in Microsoft Windows, assicurarsi di eseguire il File -> Converti delimitatori di linea in -> Unix .

  6. Imposta una configurazione di avvio del debug: Esegui -> Configurazioni di debug -> Script Bash ... Ci sono 2 campi da impostare qui:

    a) "Script Bash:" - Percorso nello spazio di lavoro di Eclipse allo script Bash per il debug.
    e) "Porta debugger:" 33333

  7. Passa alla prospettiva Debug. Inizia la sessione di debug. Lancio script.shdalla bash shell.

L'interfaccia utente di debug bash

inserisci qui la descrizione dell'immagine

Questo debugger bash ha tutte le funzionalità dei debugger di programmazione standard come:

  • Attiva / disattiva punto di interruzione
  • Operazione singola passo-passo
  • Funzioni step-in, step-out, step-over e routine secondarie
  • Esame del codice o delle variabili in qualsiasi momento durante l'esecuzione dello script

L' IDE Shelled (Shell Script Editor) (Integrated Development Environment) ha un ulteriore vantaggio di eseguire il controllo del contesto, l'evidenziazione e il rientro durante la scrittura dello script. Se non rientra correttamente, potresti immediatamente essere in grado di contrassegnare / localizzare molti errori lì.

Quindi ci sono altri vantaggi IDE come:

  • Elenco attività TODO
  • Mylyn Task
  • Elenco dei segnalibri
  • Modifica di più finestre
  • Condivisione remota dell'ambiente

Suggerimento interessante. Bello sapere che Bash può essere debug in questo modo.
slm

8

Una risorsa meravigliosa è apparsa negli ultimi anni: http://shellcheck.net

ti mostra più del normale bash, permettendoti di trovare facilmente quelle fastidiose citazioni chiuse o parentesi graffe, ecc.

Assicurati solo di non incollare informazioni sensibili (ips, password, ecc.) Sulla rete ... (specialmente perché è http, non crittografato) (credo che shellcheck sia disponibile anche per il download, ma non sono sicuro)


6

usa semplicemente:

#!/bin/bash -x

lo stesso per la shell:

#!/bin/sh -x

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.