Reputation: 3837
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!
Upvotes: 12
Views: 6719
Reputation: 7367
In case anyone finds this question through Google, I solved this 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 results in /tmp/trace having contents 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 every command that is run 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
would otherwise include>> /tmp/trace
appends the complete string to the file you specify. (I'd advise against anything in /tmp/
unless you want it to be deleted when you restart the computer.)Upvotes: 5
Reputation: 5455
You can use trap with DEBUG to do this, like trap 'a oneliner in here' DEBUG
.
Upvotes: 3
Reputation: 31182
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
Upvotes: 10
Reputation: 263217
$PROMPT_COMMAND
, if set, contains a command to execute before printing the prompt ($PS1
). Set it to the name of a function that captures the output of history 1
.
Upvotes: 4
Reputation: 592
Not sure about intercepting every command but in some versions of Linux every command gets logged to ~/.bash_history. You could either figure out how that works or just parse that file to see the last command.
Upvotes: 1