Is there a way to intercept every command given to bash
? I can intercept a particular command, e.g., cd
by defining a function cd()
and I can do that for one-command-at-a-time for other commands as well. But can I write a function which gets called before every command is executed? I want to do some bookkeeping of commands, and then executed the command.
Michał Šrajer's idea PS4='$(echo $(date) $(history 1) >> /tmp/trace.txt) TRACE: '
looks very promising but here is the output 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
get written in /tmp/trace.txt exactly 5 times. The four other ones comes from my definition of PS1
where I run the following command: $(git branch 2> /dev/null | grep -e "\* " | sed "s/^..\(.*\)/ {\1}/")
. Two questions:
/tmp/trace.txt
exactly? /tmp/trace.txt
? I am so excited about the possibility of being able to record commands from all my bash sessions in one place!
$() means: "first evaluate this, and then evaluate the rest of the line". Ex : echo $(pwd)/myFile.txt. will be interpreted as echo /my/path/myFile.txt. On the other hand ${} expands a variable.
$_ (dollar underscore) is another special bash parameter and used to reference the absolute file name of the shell or bash script which is being executed as specified in the argument list. This bash parameter is also used to hold the name of mail file while checking emails. $@
A built-in bash command that is used to execute a command when the shell receives any signal is called `trap`. When any event occurs then bash sends the notification by any signal. Many signals are available in bash. The most common signal of bash is SIGINT (Signal Interrupt).
To split long commands into readable commands that span multiple lines, we need to use the backslash character (\). The backslash character instructs bash to read the commands that follow line by line until it encounters an EOL.
You can set the PS4 variable, which is evaluated for every command being executed just before the execution if trace is on:
PS4='$(echo $(date) $(history 1) >> /tmp/trace.txt) TRACE: '
Then, enable trace:
set -x
To stop tracing, just:
set +x
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With