ShellLogger captures all user interactions with a shell. It is intended to be used for software engineering researchers who are interested in inferring programmer behavior from data that can be captured automatically during a programming session. It is similar to the Unix "script" program, with the following additional features:
- Automatically distinguishes between the text that was inputted by the user and the data that was output by the shell and other programs
- Records timestamps of when data was inputted by user and when the system responds
- Tracks directory information
- Actually deletes characters when user hits backspace, rather than capturing the backspace character.
- Can disable capturing output when certain terminal-based programs are invoked (e.g. Emacs, vi)
- Records the data in an XML file to facilitate parsing by other applications
For questions about ShellLogger, please contact Lorin Hochstein: lorinh@gmail.com.
ShellLogger requires Python 2.1 or higher. It works with either bash or tcsh.
- python setup.py install (you need root access for this)
(Optionally:)
Modify the appropriate startup settings file (e.g. .profile, .cshrc) to invoke ShellLogger on startup, by adding it to the end of the file, e.g.:
python /usr/local/bin/shelllogger
If you want to avoid requiring the user to type "exit" twice to logout (once to exit ShellLogger, and again to exit the parent shell), you can add the following code:
# in bash if [ -z "$ShellLogger" ] then exit fi # in tcsh if !($?ShellLogger) then exit endif
Make sure you get this part right. If the "exit" is unconditionally executed in this file, the poor user will log out automatically as soon as they log in!
If you want to change the location where ShellLogger puts files (default is
~/.shelllogger
directory), define and export a SHELLLOGGERDIR environment variable:# in bash export SHELLLOGGERDIR='/Users/lorin/mydata/shelllogger' # in tcsh setenv SHELLLOGGERDIR '/Users/lorin/mydata/shelllogger'
Putting it all together, your bash .profile would end with:
export SHELLLOGGERDIR='/Users/lorin/mydata/shelllogger' python /Users/lorin/scripts/shelllogger if [ -z "$ShellLogger" ] then exit fi
Your tcsh .cshrc would then end with:
setenv SHELLLOGGERDIR '/Users/lorin/mydata/shelllogger' python /Users/lorin/scripts/shelllogger if !($?ShellLogger) then exit endif
Usage:
[~]$ shelllogger <logfilename>
ShellLogger will begin logging until you exit the shell. Upon exit, a
log of the data named <logfilename> will be generated in the directory where
ShellLogger was invoked. If no logfile is specified, it will default to
~/.shelllogger/log.<tstamp>.xml
where <tstamp> is the UTC timestamp when
the shelllogger session was started.
The output of ShellLogger looks like the following:
<cli-logger> <cli-logger-entry> <invocation time="1185080805.408457" current-directory="/Users/lorinh/shelllogger" machine="Bender.local"><![CDATA[ pwd ]]></invocation> <result time="1185080805.408832"><![CDATA[ /Users/lorinh/shelllogger ]]></result> </cli-logger-entry> <cli-logger-entry> <invocation time="1185080806.856568" current-directory="/Users/lorinh/shelllogger" machine="Bender.local"><![CDATA[ ls ]]></invocation> <result time="1185080806.862642"><![CDATA[ shelllogger package readme.html readme.txt ]]></result> </cli-logger-entry> <cli-logger-entry> <invocation time="1185080808.744830" current-directory="/Users/lorinh/shelllogger" machine="Bender.local"><![CDATA[ cd package ]]></invocation> <result time="1185080808.745676"></result> </cli-logger-entry> <cli-logger-entry> <invocation time="1185080812.328699" current-directory="/Users/lorinh/shelllogger/package" machine="Bender.local"><![CDATA[ cat README ]]></invocation> <result time="1185080812.334055"><![CDATA[ This directory contains the script for packaging up ShellLogger for distribution. ]]></result> </cli-logger-entry> <cli-logger-entry> <invocation time="1185080813.616734" current-directory="/Users/lorinh/shelllogger/package" machine="Bender.local"><![CDATA[ exit ]]></invocation> <result time="1185080813.617144"><![CDATA[ exit ]]></result> </cli-logger-entry> </cli-logger>
Most likely, you will not want to capture the output of terminal-based programs, such as Emacs or vi. If you plan to use such a program, and don't want its output captured, specify the program in the TERMINAL_APPS variable defined in shelllogger.
It has only been tested on a small number of systems, and terminal behavior varies widely, so certain things may not work on certain terminals. In particular, detecting backspace and shell termination are known to not work properly on some platforms right now.
Does not handle things properly if you move the cursor around using the arrows keys or Control-A, Control-K. (It will handle backspace, though).