In my code, I use popen with cmd 'iostat -xk 2 2'. Generally the iostat cmd will output a report to stdout and sleep for interval 2 seconds, then output another report to stdout.
When I use fgets to read from popen pipe, weird things are: I only get the first report. fgets hangs there and I never get the second report 2 seconds later. I change the function fgets to fgetc but it didn't help.
Here is my C++ code:
string iostatCMD = string("iostat -xk 2 2 ");
FILE *iostatFile = popen(iostatCMD.c_str(), "r");
int fd = fileno(iostatFile);
string readall;
while(!feof(iostatFile))
{
char buffer[128];
if (fgets(buffer, 128, iostatFile) != NULL)
{
cout <<buffer;
readall += buffer;
}
}
cout <<"readall = " <<readall <<endl;
I give it a try with Python. It works very well with popen, I get two reports by iostat and no hangs:
subprocess.Popen('iostat -xk 2 2', shell=True, stdout=subprocess.PIPE).communicate()[0];
So my question is how to read continuely all the output from popen pipe in C++?
Related
Today I have been facing a critical bug in my program, it is just a tiny code that uses popen() to pass the commands and pipe its results to a file descriptor where I use fgets() to read the result, The problem for date command my program is been hanging(waiting) and the reason is as we know after issuing date it will show the current date and issues a yes or no question like the below.
The current date is: Fri 08/21/2015
Enter the new date: (mm-dd-yy)----this was shitting my code!!!!
I just want my program to skip this questionnaire.
Note: the string "command" in the below code is what I will receive from the user.
FILE *in;
char buff[512];
string cmd;
command += " 2>&1";
if (!(in = popen(command.c_str(), "r"))) {
status = "0"; // my logic don't bother:)
}
else {
while (fgets(buff, sizeof(buff), in) != NULL) {
cmd += buff;
}
}
Thanks to Petesh.
I have changed to 2>&1<nul instead of 2>&1, the program isn't hanging now,
The key to this solution is adding <nul gives some default value as an answer to the prompts.
My C++ program creates a subprocess to call a python script that does not terminate, but I also want to know what's happening in that subprocess by retrieving its (the python subprocess) stdout in my main program C++. I have the following code. In this case, I am only interested in the first line of stdout of the python program.
FILE *fp;
char *line = (char*)malloc(1024 * sizeof(char));
int index = 0;
char c;
fp = popen("python testing.py run_for_long_time", "r");
while (true)
{
c = fgetc(fp);
if (c == '\n') {
break;
}
line[index++] = c;
}
line[index] = '\0';
printf("Finished\n");
I noticed that the code does not print out finished until the subprocess has terminated (but I am only interested in the first line of the subprocess stdout so I don't want to wait for subprocess termination).
How can I do this with popen and file descriptor?
Thanks to #ArtemGr, it turns out that I just need to enable python buffering. See
Disable output buffering
I try to redirect output in my c++ program from stdout with the following:
freopen(cmd.c_str(),"w",stdout);
Then I call system to execute cmd. I have also tried forking and then calling execvp. Either way, when program control returns to my program, things written to stdout are no longer showing. How can normal behavior be restored?
Here is solution for stdin if doing in loop, needed to figure this out for a program wherein freopen of stdin happens in a loop on some condition. Took some time for me to figure out (with help of search and all) and so posting here
savestdin = dup(STDIN_FILENO);
while (1) {
.
.
if (inputfile) {
savestdin = dup(savestdin);
freopen(inputfile, "r", stdin);
restorestdin = TRUE;
}
.
.
if (restorestdin) {
fflush(stdin);
fclose(stdin);
stdin = fdopen(savestdin, "r");
restorestdin = FALSE;
}
.
.
}
Do this:
fclose(stdout);
stdout = fdopen(1, "w"); //reopen: 1 is file descriptor of std output
If you can use STDOUT_FILENO from <unistd.h>, instead of 1 as first argument to fdopen.
I am developing an application, in which I want to redirect the output (progress information) of dd command to my C++ program, but it is not actually getting the output, here is the code
FILE * progressInfo = popen("gzip -dc backup/backup.img.gz | pv -ptrbe -i 2 -s 2339876653 | dd of=/dev/sdb","r");
if(!progressInfo)
{
return -1;
}
char buf[1024];
while(fgets(buff, sizeof(buff),progressInfo)!=NULL)
{
std::cout << buff << endl;
}
but the problem is the progress information is not received in buff, and the output is continuously printed on terminal, and above program halts on while(fgets(buff, sizeof(buff),progressInfo)!=NULL), and as soon as the dd operation is completed, the very next line to loop block is executed.
if anyone has any idea why the output is not returned to buff, and its continuously retuned on terminal?
The output is probably being written to standard error rather than standard output. Just add " 2>&1" to the very end of your command string and you should see the output (note the leading space).
Is that even possible ?
Lets say that the code has a lot of scanf lines. Instead of manually running and adding values by hand when debugging, is it possible to "feed" stdin with data so that when the scanf starts reading, it will read the inputted data without any need to interact with the terminal.
Put the test lines into a file, and run the program like this:
myprogram < mytestlines.txt
Better than hacking your program to somehow do that itself.
When you're debugging the code, you can set up the debugger to run it with that command line.
To make your program a little more versatile, you might want to consider rewriting your program to use fscanf, fprintf, etc. so that it can already handle file IO as opposed to just console IO; then when you want to read from stdin or write to stdout, you would just do something along the lines of:
FILE *infile, *outfile;
if (use_console) {
infile = stdin;
outfile = stdout;
} else {
infile = fopen("intest.txt", "r");
outfile = fopen("output.txt", "w");
}
fscanf(infile, "%d", &x);
fprintf(outfile, "2*x is %d", 2*x);
Because how often do programs only handle stdin/stdout and not allow files? Especially if you end up using your program in shell scripts, it can be more explicit to specify input and outputs on the command line.
int fd[2];
pipe(fd);
close(0); // 0:stdin
dup(fd[0], 0); // make read pipe be stdin
close(fd[0]);
fd[0] = 0;
write(fd[1], "some text", 9); // write "some text" to stdin