Bash: how to intercept every command

Is there a way to intercept every command specified in bash ? I can intercept a specific command, for example, cd , by defining a cd() function, and I can do this for one command in time for other commands. But can I write a function that is called before each command? I want to execute some commands and then execute the command.

Michal Šrajer idea PS4='$(echo $(date) $(history 1) >> /tmp/trace.txt) TRACE: ' looks very promising, but here is the result that I get:

 $ ping www.google.com TRACE: ping www.google.com PING www.l.google.com (74.125.224.52) 56(84) bytes of data. 64 bytes from 74.125.224.52: icmp_seq=1 ttl=56 time=3.77 ms 64 bytes from 74.125.224.52: icmp_seq=2 ttl=56 time=2.33 ms ^C --- www.l.google.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1001ms rtt min/avg/max/mdev = 2.334/3.054/3.774/0.720 ms TRACE: echo -ne '\033]0;myhost.com /home/yogeshwer/github/myproject\007' TRACE: grep -e '\* ' TRACE: git branch TRACE: sed 's/^..\(.*\)/ {\1}/' 

And Wed Aug 3 12:47:27 PDT 2011 6672 ping www.google.com written to /tmp/trace.txt exactly 5 times. Four others from my definition of PS1 , where I run the following command: $(git branch 2> /dev/null | grep -e "\* " | sed "s/^..\(.*\)/ {\1}/") . Two questions:

  • Is it possible to write the /tmp/trace.txt command /tmp/trace.txt ?
  • And more importantly, is it possible not to clutter up the output of the command, but just write the command /tmp/trace.txt ?

I am very happy to be able to record commands from all my bash sessions in one place!

+7
source share
5 answers

You can set the PS4 variable, which is evaluated for each command executed just before execution, if tracing is enabled:

 PS4='$(echo $(date) $(history 1) >> /tmp/trace.txt) TRACE: ' 

Then enable tracing:

 set -x 

To stop the trace, simply:

 set +x 
+8
source

$PROMPT_COMMAND , if set, contains a command to execute before printing the request ( $PS1 ). Set it to the name of the function that displays the history 1 output.

+4
source

If someone finds this question via Google, I solved it by adding the following to my ~/.bashrc .

 PROMPT_COMMAND='echo "$(date +"%Y/%m/%d (%H:%M)") $(history 1 |cut -c 7-)" >> /tmp/trace' export PROMPT_COMMAND 

This causes / tmp / trace to have content such as

 2015/01/21 (14:34) pwd 2015/01/21 (14:36) less /tmp/trace 2015/01/21 (14:36) cd Documents 2015/01/21 (14:36) cd .. 2015/01/21 (14:36) ls -la 2015/01/21 (14:36) pwd 2015/01/21 (14:36) echo "helloWorld" 
  • PROMPT_COMMAND is executed after each command which is executed through bash
  • $(date +"%Y/%m/%d (%H:%M)") prints the date and time
  • $(history 1 |cut -c 7-) prints the command
    • cut -c 7- removes the number that history otherwise includes
  • >> /tmp/trace adds the entire line to the file you specify. (I would advise nothing in /tmp/ if you do not want to be deleted when you restart your computer.)
+2
source

Not sure about intercepting every command, but on some versions of Linux, every command is written to ~ / .bash_history. You can either figure out how this works, or simply analyze this file to see the last command.

+1
source

You can use trap with DEBUG for this, for example trap 'a oneliner in here' DEBUG .

+1
source

All Articles