我正在越来越多地使用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,我会在一两次迭代中中止,但我想知道,有没有更有效的方法来实现这种行为?
答案 0 :(得分:3)
John,我不确定这是否会有所帮助,但是通过调查setTimeLimit
,我了解到只要用户能够执行中断(例如Ctrl-C),它就可以暂停执行。有关一些参考资料,请参阅this question。
特别是回调可能是最佳选择,我会查看addTaskCallback
和this guide on developer.r-project.org。
以下是其他四条建议:
虽然这是一个hack,一种非常不同的方法,我可以调用两个R会话,一个是主会话,另一个只是存在来执行主会话传递的shell命令,它只等待确认在开始下一个工作之前完成了这项工作。
如果您可以使用foreach
代替for
(并行,通过%dopar%或序列%do%而不是%dopar%或w /只有1名注册工作人员) ,这可能更容易受到干扰,因为它可能等同于第一个建议(因为它分叉R)。
如果您可以检索外部命令的退出代码,那么可以将其传递给有条件的循环。 This previous Q&A在这方面会有所帮助。
如果你想让一切都在一个bash脚本中运行,那么R就可以编写一个长脚本(即将一个字符串或一系列字符串输出到一个文件中)。这可以执行,并且保证中断不会影响循环,因为您已经展开循环。或者,您可以在bash中编写循环。 Here are examples。就个人而言,我喜欢使用find
(例如find .... -exec doStuff {} ';'
)或通过反引号作为输入将命令应用于文件。不幸的是,我不能轻易地在SO上提供格式良好的代码,因为它将反引号嵌入反引号... See this page for examples因此,可能是你可以有一个命令,没有循环,并应用一个对满足特定标准集的所有文件起作用。通过反引号使用命令替换对于bash用户来说是一个非常方便的技巧。
答案 1 :(得分:0)
您应该检查每次system()
的呼叫是否都具有非零退出状态。如果出现意外错误,您的程序应stop()
,否则您可能会收到意外结果。当你用 Ctrl + C 杀死时,你调用的程序应该返回一个非零退出状态,如果没有,那就是这些程序中的错误或缺陷