Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Let Bash trap DEBUG see pipe as one command

Tags:

bash

I am using

trap 'echo -e "\e[92m$ $BASH_COMMAND\e[0m"' DEBUG

in a Bash script to print every command that is executed.

This works fine, except that it prints two commands when I pipe them together:

bzip2 -dc < dump.sql.bz2 | mysql test

Prints:

$ bzip2 -dc < dump.sql.bz2
$ mysql test

Can I make any change to the trap or to the line with the pipe so that the line will be printed as one?

like image 991
AndreKR Avatar asked Apr 24 '16 13:04

AndreKR


People also ask

Does bash have debug traps?

We can utilize the DEBUG trap feature of Bash to execute a command repetitively. The command specified in the arguments of trap command is executed before each subsequent statement in the script.

How do you see is command is executed in bash?

Now, every command run in bash shell returns a value that's stored in the bash variable “$?”. To get the value, run this command. $ echo $? If a command succeeded successfully, the return value will be 0.

What does trap command do in bash?

If you've written any amount of bash code, you've likely come across the trap command. Trap allows you to catch signals and execute code when they occur. Signals are asynchronous notifications that are sent to your script when certain events occur.

How do I run a shell script in verbose mode?

The -v option tells the shell to run in verbose mode. In practice, this means that the shell will echo each command prior to executing the command. This will be useful in locating the line of script that has created an error.


2 Answers

Change your command to:

mysql test < <(bzip2 -dc < dump.sql.bz2)

Using a process substitution instead of a pipeline makes the command a simple command from Bash's perspective, which is the level of granularity at which the DEBUG trap and the built-in $BASH_COMMAND variable operate.

Background:

The DEBUG (pseudo) signal by design operates on the level of simple commands, as does $BASH_COMMAND.

bzip2 -dc < dump.sql.bz2 | mysql test is a pipeline composed of multiple simple commands.

Therefore, your trap statement cannot do what you want with a pipeline.

The closest thing to getting what you want with a compound command (e.g., a while loop or a command group ({ ...; ...; }) or a command list (simple commands or pipelines joined with operators ; && || &) is to use set -v, which echoes the entire command to stderr before it is executed, but I wouldn't know how to control the formatting of this output.

like image 185
mklement0 Avatar answered Nov 10 '22 06:11

mklement0


A crude workaround would be using a function, like this:

run () { eval $1; }
trap 'echo -e "\e[92m$ $BASH_COMMAND\e[0m"' DEBUG
run "bzip2 -dc < dump.sql.bz2 | mysql test"

Output:

$ run "bzip2 -dc < dump.sql.bz2 | mysql test"
like image 3
AndreKR Avatar answered Nov 10 '22 05:11

AndreKR