Can system() return before piped command is finished
I am having trouble using system() from libc on Linux. My code is this:
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;
I run this snippet repeatedly and occasionally I find that count == 0 at the end of the run - no lines have been read from the file. I look at the file system and the file has the contents I would expect (greater than zero lines).
My question is should system() return when the entire command passed in has completed or does the presence of the pipe '|' mean system() can 开发者_如何学JAVAreturn before the part of the command after the pipe is completed?
I have explicitly not used a '&' to background any part of the command to system().
To further clarify I do in practice run the code snippet multiples times in parallel but the output file is a unique filename named after the thread ID and a static integer incremented per call to system(). I'm confident that the file being output to and read is unique for each call to system().
According to the documentation
The system() function shall not return until the child process has terminated.
Perhaps capture the output of "output" when it fails and see what it is? In addition, checking the return value of system
would be a good idea. One scenario is that the shell command you are running is failing and you aren't checking the return value.
system(...)
calls the standard shell to execute the command, and the shell itself should return only after the shell has regained control over the terminal. So if there's one of the programs backgrounded, system will return early.
Backgrounding happens through suffixing a command with &
so check if the string you pass to system(...)
contains any &
and if so make sure they're properly quoted from shell processing.
System will only return after completion of its command and the file output
should be readable in full after that. But ...
... multiple instances of your code snippet run in parallel would interfere because all use the same file output
. If you just want to examine the contents of output
and do not need the file itself, I would use popen
instead of system
. popen
allows you to read the output of the pipe via a FILE*
.
In case of a full file system, you could also see an empty output
while the popen
version would have no trouble with this condition.
To notice errors like a full file system, always check the return code of your calls (system, popen, ...). If there is an error the manpage will tell you to check errno
. The number errno
can be converted to a human readable text by strerror
and output by perror
.
精彩评论