从 R 中的系统调用捕获退出状态和输出
Posted
技术标签:
【中文标题】从 R 中的系统调用捕获退出状态和输出【英文标题】:Capture both exit status and output from a system call in R 【发布时间】:2011-10-24 06:03:41 【问题描述】:我一直在玩system()
和system2()
来取乐,令我震惊的是我可以将输出或退出状态保存在一个对象中。一个玩具例子:
X <- system("ping google.com",intern=TRUE)
给我输出,而
X <- system2("ping", "google.com")
给我退出状态(在这种情况下为 1,谷歌不接受 ping)。如果我想要输出和退出状态,我必须进行 2 次系统调用,这似乎有点矫枉过正。仅使用一个系统调用如何实现两者?
编辑:如果可能的话,我希望将两者都放在控制台中,而无需在 system2
调用中使用 stdout="somefile.ext"
并随后将其读入。
【问题讨论】:
您使用的是 Linux 还是 Windows?我什至无法让 stdout="somefile.ext" 在 Windows 上运行,但它在 Linux 上运行良好...... 我建议将linux
与您使用的任何外壳一起添加到您的标签中。这可以邀请操作系统专家的一些解决方案。
向 OP 和 @Gavin 道歉,我可能弄错了:我认为这是明确或隐含的 Linux,但我看到 OP 甚至没有提到 Linux,据我所知,它可能是另一个操作系统.
它不是 Linux,甚至不是特定于操作系统的。这是关于 R 代码的。
【参考方案1】:
从 R 2.15 开始,system2
将在 stdout
和/或 stderr
为 TRUE 时将返回值作为属性提供。这使得获取文本输出和返回值变得容易。
在这个例子中,ret
最终是一个带有属性"status"
的字符串:
> ret <- system2("ls","xx", stdout=TRUE, stderr=TRUE)
Warning message:
running command ''ls' xx 2>&1' had status 1
> ret
[1] "ls: xx: No such file or directory"
attr(,"status")
[1] 1
> attr(ret, "status")
[1] 1
【讨论】:
【参考方案2】:我对你对 system2 的描述有点困惑,因为它有 stdout 和 stderr 参数。所以它能够返回退出状态,stdout 和 stderr。
> out <- tryCatch(ex <- system2("ls","xx", stdout=TRUE, stderr=TRUE), warning=function(w)w)
> out
<simpleWarning: running command ''ls' xx 2>&1' had status 2>
> ex
[1] "ls: cannot access xx: No such file or directory"
> out <- tryCatch(ex <- system2("ls","-l", stdout=TRUE, stderr=TRUE), warning=function(w)w)
> out
[listing snipped]
> ex
[listing snipped]
【讨论】:
+1 非常好。顺便说一句,欢迎来到 SO,不是每个人都会阅读 R 命令的帮助信息。 ;-) +1,因为它使用了 R 的内部警告和错误技巧。我可以从警告消息中删除退出状态。我知道我可以使用 stdout=TRUE,但退出状态是我主要关心的问题。这就是我没有这样做的原因。 似乎无论如何都是这样做的,所以这将是公认的答案。 当我运行第一个命令 (ls xx
) 时,我收到了与 out
相同的警告消息,但根本没有设置 ex
。这适用于 Mac 和 Linux 上的 R 2.14.2。有没有其他方法可以做到这一点?【参考方案3】:
我建议在这里使用这个功能:
robust.system <- function (cmd)
stderrFile = tempfile(pattern="R_robust.system_stderr", fileext=as.character(Sys.getpid()))
stdoutFile = tempfile(pattern="R_robust.system_stdout", fileext=as.character(Sys.getpid()))
retval = list()
retval$exitStatus = system(paste0(cmd, " 2> ", shQuote(stderrFile), " > ", shQuote(stdoutFile)))
retval$stdout = readLines(stdoutFile)
retval$stderr = readLines(stderrFile)
unlink(c(stdoutFile, stderrFile))
return(retval)
这仅适用于接受 > 和 2> 符号的类 Unix shell,并且 cmd 参数不应重定向输出本身。但它确实有效:
> robust.system("ls -la")
$exitStatus
[1] 0
$stdout
[1] "total 160"
[2] "drwxr-xr-x 14 asieira staff 476 10 Jun 18:18 ."
[3] "drwxr-xr-x 12 asieira staff 408 9 Jun 20:13 .."
[4] "-rw-r--r-- 1 asieira staff 6736 5 Jun 19:32 .Rapp.history"
[5] "-rw-r--r-- 1 asieira staff 19109 11 Jun 20:44 .Rhistory"
$stderr
character(0)
【讨论】:
谢谢,这很好用!这确实应该是 R 中的默认功能。以上是关于从 R 中的系统调用捕获退出状态和输出的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核进程管理 ( 进程状态 | 进程创建 | 进程终止 | 调用 exit 系统调用函数主动退出 | main 函数返回自动退出 | kill 杀死进程 | 执行异常退出 )