bash: how to intercept every command
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: ic开发者_StackOverflow中文版mp_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:
- Is it possible to write the command to
/tmp/trace.txt
exactly? - And more importantly, is it possible to not clutter the output of the command, but only write the command to
/tmp/trace.txt
?
I am so excited about the possibility of being able to record commands from all my bash sessions in one place!
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
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 commandcut -c 7-
removes the number thathistory
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.)
$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
.
You can use trap with DEBUG to do this, like trap 'a oneliner in here' DEBUG
.
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.
精彩评论