If, like me, you spend your day working at the command line (for me, mostly at the Bash and R shells in Linux) knowing what commands you’ve typed (and when and where) can be very useful.
Adding the following line (substitute ‘AGW’ for whatever you like) will result in all your commands entered at the Bash command line (along with date and filesystem location) being logged in a file (in this case, ~/.bash_history.AGWcomplete
).
1 |
export PROMPT_COMMAND='export time_AGW=`date`; echo $(history 1) " " $time_AGW " " $HOSTNAME >> .bash_history.AGW;export tail_AGW=`tail -n 1 .bash_history.AGW`;echo $tail_AGW " " $PWD >> ~/.bash_history.AGWcomplete' |
Each directory where commands are run also gets its own history file (.bash_history.AGW
). Very useful if you want to know the genesis of a particular file in a directory.
Although I did not use it, S-Plus apparently had an audit function that would record commands executed on the shell into a log file. Auditing functionality is sometimes mentioned as a reason for the popularity of SAS in the pharmaceutical industry. But logging your work is of more general interest than meeting regulatory guidelines. In R, if you’re doing some initial exploration of a data set and your session crashes, your work will be lost, unless you remembered to savehistory()
. Having a log also helps if you want to check how some analysis was performed.
I have a file (/AGW_functions.R) with custom functions (e.g. shortcuts to open tab-delimited files, sort data frames, run Gene Ontology enrichment analysis, …) that gets loaded when I start up an R session. The following 3 functions permit ‘auditing':
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
############## ## Auditing ## ############## # modified from history() agw.last.cmd <- function() { file <- tempfile("Rrawhist.AGW") savehistory(file) rawhist <- readLines(file) nlines <- length(rawhist) return(rawhist[nlines]) } agw.audit <- function() { last.cmd <- agw.last.cmd() #print(last.cmd) row <- paste(last.cmd, getwd(), date(), sep=" *** ") agw.write.row(row, "~/audit.R") } # http://stackoverflow.com/questions/4222476/r-display-a-time-clock-in-the-r-command-line if ( !any(commandArgs()=='--no-readline') && interactive() ) { tm <- taskCallbackManager() tm$add(function(...) { savehistory() agw.audit() return(TRUE) }, name = "RhistoryHandler" ) } |
In my .Rprofile
, the following lines load my custom R file at startup:
1 2 3 |
.startup <- new.env() sys.source("/AGW_functions.R", .startup) attach(.startup) |
Now every command I execute in the R shell gets recorded in ~/audit.R
.
ETA: While Googling to see if this page is already indexed, I found the following:
http://www.jefftk.com/news/2010-08-04
http://www.jefftk.com/news/2012-02-13
This fellow and I share much of the rationale for wanting to do this logging. Like him, I’m also surprised that more people are not doing it. I liked the following comment at the 2nd link. It’s a great illustration of how useful pervasive logging can be:
Thanks for this tip — I’ve been using it for about six months now and it’s definitely saved me a couple of times. (Just this morning I was trying to figure out where on earth I put an essential archive of data from a decommissioned server about a month ago, which I need to unpack onto a new server today — I couldn’t remember what I had named the archive or even whether I left it on my own computer or moved it to another server somewhere, so find wasn’t helpful. Eventually I thought to grep my ~/.full_history for “scp” and the IP of the decommissioned server. Definitely wouldn’t have found it any other way.)