中断循环与系统命令

时间:2011-11-11 16:25:11

标签: r

我正在越来越多地使用Rscript,而我通常会使用bash脚本。一个小烦恼是,许多这些脚本循环一些system()调用,如果我试图中断它,R基本上没有时间来捕获我的控制-c。相反,它只是中止正在运行的系统命令并继续下一个循环迭代。例如,当我尝试通过按住control-c来中断以下操作时,它仍然会通过所有迭代:

for(i in 1:10) {
  cat(i)
  system('sleep 3')
}

到目前为止,我总是通过在每个循环中插入一个小暂停来解决这个问题,如

for(i in 1:10) {
  Sys.sleep(0.25)
  cat(i)
  system('sleep 3')
}

如果我按住control-c,我会在一两次迭代中中止,但我想知道,有没有更有效的方法来实现这种行为?

2 个答案:

答案 0 :(得分:3)

John,我不确定这是否会有所帮助,但是通过调查setTimeLimit,我了解到只要用户能够执行中断(例如Ctrl-C),它就可以暂停执行。有关一些参考资料,请参阅this question

特别是回调可能是最佳选择,我会查看addTaskCallbackthis guide on developer.r-project.org

以下是其他四条建议:

  1. 虽然这是一个hack,一种非常不同的方法,我可以调用两个R会话,一个是主会话,另一个只是存在来执行主会话传递的shell命令,它只等待确认在开始下一个工作之前完成了这项工作。

  2. 如果您可以使用foreach代替for(并行,通过%dopar%或序列%do%而不是%dopar%或w /只有1名注册工作人员) ,这可能更容易受到干扰,因为它可能等同于第一个建议(因为它分叉R)。

  3. 如果您可以检索外部命令的退出代码,那么可以将其传递给有条件的循环。 This previous Q&A在这方面会有所帮助。

  4. 如果你想让一切都在一个bash脚本中运行,那么R就可以编写一个长脚本(即将一个字符串或一系列字符串输出到一个文件中)。这可以执行,并且保证中断不会影响循环,因为您已经展开循环。或者,您可以在bash中编写循环。 Here are examples。就个人而言,我喜欢使用find(例如find .... -exec doStuff {} ';')或通过反引号作为输入将命令应用于文件。不幸的是,我不能轻易地在SO上提供格式良好的代码,因为它将反引号嵌入反引号... See this page for examples因此,可能是你可以有一个命令,没有循环,并应用一个对满足特定标准集的所有文件起作用。通过反引号使用命令替换对于bash用户来说是一个非常方便的技巧。

答案 1 :(得分:0)

您应该检查每次system()的呼叫是否都具有非零退出状态。如果出现意外错误,您的程序应stop(),否则您可能会收到意外结果。当你用 Ctrl + C 杀死时,你调用的程序应该返回一个非零退出状态,如果没有,那就是这些程序中的错误或缺陷