2011-06-17 81 views
2

我在Linux上使用libc中的system()時遇到了問題。我的代碼是這樣的:系統()可以在管道命令完成之前返回

system("tar zxvOf some.tar.gz fileToExtract | sed 's/some text to remove//' > output"); 

std::string line; 
int count = 0; 
std::ifstream inputFile("output"); 
while(std::getline(input, line != NULL)) 
    ++count; 

我反覆運行這個片段偶爾我發現在運行結束即計數== 0 - 無行已經從文件中讀取。我查看文件系統,文件中包含我期望的內容(大於零行)。

我的問題是系統()返回,當整個命令傳入已完成或存在的管道'|'意味着system()可以在管道完成後的命令部分之前返回?

我已明確未使用「&」到背景的任何命令的系統部分()。

爲了進一步闡明我在實踐中做運行該代碼段的倍數倍平行但輸出文件是線程ID和()每個呼叫遞增到系統中的靜態整數命名的唯一的文件名。我相信,每次調用system()時,輸出到並讀取的文件都是唯一的。

+0

你有沒有發現爲什麼計數有時是零,當你認爲它不應該是? – 2011-06-17 17:23:35

回答

3

按照documentation

系統()函數將不會返回直到子進程已經終止。

也許在失敗時捕獲「輸出」的輸出,看看它是什麼?另外,檢查system的返回值將是一個好主意。一種情況是您運行的shell命令失敗,並且您沒有檢查返回值。

+0

這是一個好主意,我會做。但是,我可以看到文件按預期提取,這意味着系統命令正在成功完成。我的問題是爲什麼在system()調用之後嘗試讀取文件時,文件最初爲空,而當我查看文件系統時,文件非空。 – 2011-06-17 10:32:44

+0

我已經接受了你的答案,因爲它大多簡潔地回答了我關於system()的行爲的問題(管道命令**需要在system()返回之前完成)。謝謝! – 2011-06-17 10:56:23

3

system(...)調用標準shell執行命令,外殼本身應該只返回後殼已經恢復了對終端的控制。所以如果有一個方案背後,系統會提前回來。

Backgrounding發生通過後面添加&一個命令,以便檢查是否傳遞到system(...)字符串中包含任何&,如果因此要確保他們正確地從外殼加工報價。

+0

我已經編輯了這個問題,以清楚我沒有使用'&'來背景命令。雖然好點。 – 2011-06-17 10:16:36

+0

@ J.Chuchill:您確定,文本中不會有&&替代? – datenwolf 2011-06-17 10:55:24

+0

你的意思是在文本被管道sed?即使這有什麼問題?我不認爲這會被shell解釋爲後臺進程的信號,它只是sed命令的輸入的一部分,不是嗎? – 2011-06-17 11:25:49

1

系統只將其命令的完成和文件output返回後應在之後完全可讀。但是......

...你的代碼的多個實例並行代碼段運行會干擾,因爲所有使用相同的文件output。如果您只想檢查output的內容並且不需要該文件本身,則將使用popen而不是systempopen允許您通過FILE*讀取管道輸出。

如果是完整的文件系統,您也可以看到一個空的output,而popen版本不會遇到這種情況。

要發現類似完整文件系統的錯誤,請務必檢查您的調用(系統,popen,...)的返回碼。如果出現錯誤,聯機幫助頁會告訴您檢查errno。數字errno可以通過strerror轉換爲人類可讀文本並由perror輸出。

+0

感謝您的回答 - 我很欣賞您的觀點,並編輯了我的問題來澄清。 – 2011-06-17 10:54:25