Bash – ny way to keep track of all the processes exec’d by bash

bash

I'd like to be able to keep statistics on which programs I run the most through bash. Is there any way to insert some sort of hook into bash so that it logs everything it execs?

Note that looking through the bash history file isn't good enough. I can print out the first token from each line of the history, but that doesn't get pipelines and process substitution. I'd like the following:

$ ls /usr/bin/* | fgrep $(echo grep)

to log that ls, fgrep, and echo were each run once. And the following:

$ for file in /usr/bin/*; do stat $file; echo $file; done

should note that stat and echo were run. Since for is a bash flow control statement, it wouldn't be logged.

It's debatable whether shell built-ins and functions should be logged (maybe just logged with a note about what they were). It's also debatable whether stat and echo should be logged once or however many times the loop runs in the above example. But I could work with the output whichever way was easiest.

Running bash with -x shows that it does have some internal mechanism to hook into the exec process and log what's happening. Is there any other way to get in there?

Best Answer

As a first cut at it,

strace -e execve -b execve -f -qqv -e signal='!all' bash 

for non-smoketest use you'd have to redirect stderr to some logger pipe, or litter some poor directory somewhere with files using strace's -o, maybe -o ~/commandtraces/$(date +%Y%m%d%H%M%S).$$

To do it for all interactive shells I'm thinking you'd need a guard variable in your .bashrc to avoid recursion.

Related Question