2011-06-17 83 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