2011-11-11 81 views
15

我正在越來越多地使用Rscript,我通常會使用bash腳本。一個小問題是,這些腳本中的很多會循環調用一些system()調用,如果我試圖中斷它,R基本上沒有時間讓我抓住控件c。相反,它只是中止正在運行的系統命令,並繼續進行下一個循環迭代。例如,當我試圖按住控制-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') 
} 

,讓我一個迭代兩年內終止,如果我按住Ctrl-C,但我想知道,有沒有做到這一點的行爲更有效的方式?

+0

偉大的問題。我讀過一些古魯斯的說法,任何寫得很好的程序都會聽取休息時間的按鍵,但似乎很多(當然都是我的)都沒有寫出這個功能。 –

+0

這裏也一樣!它讓我感到迷惑,因爲這些內務處理腳本通常用於設置實驗目錄區域,因此使用大量非常快速的'mkdir','chmod','ln'等命令。但是,當我必須爲1000個科目做這件事時,即使只有0.25秒的停頓時間,我每次運行一次也會有接近5分鐘的浪費。 –

+0

AFAIK一個R循環不是一個單獨的進程,所以'%kill-9 $ PID'將不起作用。但是,讓我問:你需要殺死什麼?如果是循環結束,比如說1:10000,那麼可以輸入一個每1000個週期運行一次的提示符()。如果你正在運行的腳本很長,並且在啓動它之後你改變了主意,那麼,這幾乎是你自己的錯:-)。 –

回答

3

約翰,我不確定這是否會有所幫助,但從調查setTimeLimit時,我瞭解到,只要用戶能夠執行中斷(如Ctrl-C),它就可以暫停執行。有關參考文獻,請參閱this question

特別是,回調可能是要走的路,我會檢查出addTaskCallbackthis guide on developer.r-project.org

下面是其他四個方面的建議:

  1. 雖然這是一個黑客,一個非常不同的方法我可以調用兩個R會議,一個是主會話,另一隻用來執行由通過shell命令主會話,在開始下一個會話之前,它只等待工作完成的確認。

  2. 如果您可以使用foreach代替for(無論是平行的,經由%dopar%,或串行%做%,而非%dopar%或W /只有1位註冊工人),這可能是更適合的中斷,因爲它可能相當於第一個建議(因爲它會分出R)。

  3. 如果你可以檢索的外部命令的退出代碼,則可能被傳遞到有條件的循環。 This previous Q&A在這方面會有所幫助。

  4. 如果你想擁有的一切在bash腳本運行,則R可以只寫一個腳本長(即輸出字符串或一系列的字符串到文件)。這可以被執行並且中斷被保證不會影響循環,因爲你已經展開了循環。或者,你可以在bash中編寫循環。 Here are examples。個人而言,我喜歡使用find(例如find .... -exec doStuff {} ';')將命令應用於文件,或者通過反引號作爲輸入。不幸的是,我不能輕易地在SO上提供格式良好的代碼,因爲它在反引號中嵌入了反引號......所以,可能出現這樣的情況,您可以有一個命令,不會循環,並將函數應用於所有文件符合一套特定的標準。通過反引號使用命令替換對於bash用戶來說是非常方便的技巧。

+0

感謝你,@Iterator。在過去的幾天裏,我一直在咀嚼更多的東西。回調基礎設施聽起來很有希望。我很擔心,但它會降低到同樣的問題,使我無法使用迪文的想法:我不知道「檢查按鍵」或「檢查按鈕」或類似的功能那。我當然需要仔細閱讀一些文檔,因爲有很多細節...... –

+0

其他建議也都會有用。 #1&2尤其適用於較長的腳本,我已經在使用我們的羣集調度程序,這很容易讓事情發生。儘管如此,我仍然希望有一個簡單的方法。 #3我認爲這將特別有用,因爲許多這些工具如果被中斷,確實會輸出異常狀態。 –

+0

儘管如此,我想知道如果我試圖在一個圓孔中安裝一個方形釘。爲了我在1 ... n這麼做很容易。做...;完成'在bash中,對於那些真正*很簡單的情況,也許我應該堅持下去?我不知道... –

0

您應該檢查對system()的每次調用都具有非零退出狀態。如果出現意外錯誤,您的程序應該爲stop(),否則您可能會收到意想不到的結果。當按Ctrl +ç殺死調用的程序應該返回一個非零退出狀態,如果他們不這樣做,那就是在這些程序中的錯誤或缺陷。

+0

其實我只是用'(system(「sleep」,「40」))''來測試這個,它並不表示錯誤,即使在Bash內部這樣做,所以也許我的上面的語句是錯誤的。 –