也许第一眼看到这个题目,您可能并不认为这是一个问题,因为大家都知道,R会自动在当前工作目录保存名为.Rhistory或者.Rapp.history的文件。这个文件中就是R自动保存的历史记录。但是这种自动保存的历史记录有两个缺点,第一,它只在正常退出的时候保存;第二,它有行数限制。
我提出的这个问题,其实是因为我经常遇到R崩溃的情况,或者R无限耗用内存的情况。在这些情况下,R无法正常退出,也就无法保存历史记录了。有些时候,你工作了很久,突然崩溃,而你又没有保存任何数据,是多么让人崩溃的一件事情啊。
我想着如果可以让R自动保存历史记录至一个临时文件当中,即使R崩溃了,也不至于什么都没有留下,至少还可以通过历史记录,将其重现,多好?
于是我写了如下的代码:
###################################################### #by Jianhong Ou @ umassmed @ quiworld @ Oct 22, 2013 ###################################################### Sys.setenv("tmpfile_USED_BY_autoHistorySavor" = tempfile(pattern="Rtmp.", tmpdir="~/Rtmp", fileext=".history"), "codesLines_USED_BY_autoHistorySavor" = 0) write(paste("Jianhong Ou @", format(Sys.Date(), format="%B %d %Y")) , Sys.getenv("tmpfile_USED_BY_autoHistorySavor"), sep="\n") if(interactive()){ taskCallbackManager()$add(function(expr, value, ok, visible){ write(deparse(expr), Sys.getenv("tmpfile_USED_BY_autoHistorySavor"), append=TRUE, sep="\n") Sys.setenv("codesLines_USED_BY_autoHistorySavor" = as.numeric(Sys.getenv("codesLines_USED_BY_autoHistorySavor")) + 1) return(TRUE) }, name="autoHistorySavor") } .Last <- function(){ if(interactive()){ removeTaskCallback("R-taskCallbackManager") } if(as.numeric(Sys.getenv("codesLines_USED_BY_autoHistorySavor")) < 1){ file.remove(Sys.getenv("tmpfile_USED_BY_autoHistorySavor")) } } |
把上述代码以Rprofile.site为名保存至当前R版本的etc目录下(比如Mac中的/Library/Frameworks/R.framework/Versions/3.0/Resources/etc,或者Windows中的C:\Program Files\R\R-n.n.n\etc)或者以.Rprofile为文件名保存至当前用户目录下。再运行R即可。
上述代码中,如果R正常退出,会自动删除临时文件。如果R不能正常退出,临时文件就会被保留下来。当然,我们还可以增加自动保存数据的功能,但那样会让运行变得很慢。