6

I work on a script of about 20 lines which I find myself testing time and again by copy-pasting and executing line by line.

Instead of copying-pasting each line and hitting Enter to execute, I would like to copy-paste the entire script without executing it in one go (as one block or an heredocument), but rather in a query like fashion; for example:

  • The first line get's executed regularly (unconditionally) and I am being queried if I desire to continue to execute the forthcoming line (after having enough time to consider the output);

  • If I choose to continue - so be it, if not, the operation breaks;

  • (the result so far will not be rolled back of course, but I would at least not continue to produce further problematic result);

This pattern should be repeated line after line, until the end of the script.

Is there a utility that can help me work in this fashion?

  • You can use the mentioned Bash debugger and DEBUG trap or you can show executed commands without stopping by running /bin/bash -x script.sh or using #!/bin/bash -x on the first line of the script. – jiwopene Aug 20 at 20:28
8

You could use the Bash debugger to debug your scripts.

A simpler option is to use the DEBUG trap:

#!/bin/bash

function prompt {
  if [[ -n "$BASH_COMMAND" ]]; then
    echo About to run \'$BASH_COMMAND\'
    read -p 'Continue [Y/n]?' CONT
    if [[ "$CONT" = "n" || "$CONT" = "N" ]]; then
      echo Exiting prematurely
      exit 1
    fi
  fi
}

trap prompt DEBUG

echo Hello
ls
sleep 10

This will run the prompt function before every command, once the trap is set, giving you the option to continue or abort. The lines starting with echo Hello would be replaced by whatever your script is, or better yet, you could store the function and trap command in a separate scriptlet which you’d source inside the script you want to debug.

There are some subtleties associated with the DEBUG trap; for one, it doesn’t trigger inside functions, unless it’s been re-set inside the function (so you can skip over functions you don’t want to debug, including the prompt function itself, but you need to remember to run trap inside functions you do want to debug).

The tracing behaviour can be enabled and disabled at will in your script, respectively by adding

trap prompt DEBUG

and

trap "" DEBUG

as appropriate.

  • use shopt -s extdebug if you want the DEBUG trap to be inherited by functions and subshells – mosvy Aug 21 at 8:32
  • I just tried to copy-paste everything before echo Hello; I am indeed being asked to continue or not; I have one issue - if I choose not to continue, the entire window get's closed and I lose the session; how would you tackle it? – JohnDoea Aug 30 at 19:18
  • @JohnDoea the intent here was to debug a script, not an interactive session. However, you can use this to debug an interactive session by starting a new shell inside your terminal window; that way stopping the debug session will stop the second shell, not your terminal’s main shell. – Stephen Kitt Aug 30 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.