2013-03-09 4 views
1

Я создал следующий тестовый пример для моделирования проблемы. Я скомпилировал исходный код и смог имитировать проблему.Чтение файла stdout

1) Когда системная команда, мы получили некоторую консоль (т. Е. Вашу работу), которая перенаправляется на файл с помощью dup2 и создает файл .stdout.

Когда я пытаюсь прочитать этот файл, поскольку мне нужна информация о представлении задания, и я не получал данные, которые были на консоли. Мне удалось получить данные, которые я написал (подтверждение работы файла).

Можем ли мы не читать консольный вывод из файла, который создается дочерним процессом.

* изменение rundir и CMD

#include <string> 
#include <vector> 
#include <utility> 
#include <sstream> 
#include <fstream> 
#include <iostream> 
#include <iterator> 
#include <algorithm> 
#include <functional> 
#include <map> 
#include <sys/stat.h> 
#include <fcntl.h> 
using namespace std; 
int child(); 
int main() 
{ 
    string rundir = "/temp"; 
    pid_t id =child(); 
    string _xafile; 
    string _afile; 
    string _afilecmd; 
    string line; 
    stringstream ss(stringstream::in | stringstream::out); 
    ss<<int(id); 
    _xafile = rundir; 
    _xafile = _xafile + "/" + ss.str()+".stdout"; 
    cout<<" _xafile is "<<_xafile<<endl; 
    string cmd ="cat "+ _xafile + ">" + rundir + "/" + "process.txt"; 
    _afile = rundir; 
    _afile = _afile + "/" + "process.txt"; 
    _afilecmd = "rm -rf "+ _afile; 
    system(cmd.c_str()); 
    ifstream xafile(_afile.c_str()); 
    while(xafile) 
     { 
      string word; 
      xafile >> word; 
      cout<<word<<" "; 
      /* try to read console output but did not read data */ 
     } 
    system(_afilecmd.c_str()); 
    return 0; 
} 


int child() 
{ 
    string rundir = "/tmp"; 
    string cmd = " tool <input file> -o <outputfile>"; 
    const char* std_out_file; 
    pid_t pid = fork(); 
    if (pid < 0) { 
    return -1; 
    } 
    if (pid == 0) { 
    pid_t mypid = getpid(); 
    stringstream sm; 
    sm << rundir << "/"; 
    if (strlen(std_out_file) == 0) 
     sm << mypid << ".stdout"; 
    else 
     sm << std_out_file; 

    int fd = open(sm.str().c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644); 
    dup2(fd, 1); 
    dup2(fd, 2); 
    int fd2 = open("/dev/zero", O_RDONLY); 
    dup2(fd2, 0); 
    cout<<cmd <<endl<<endl;  
    // execl("/bin/sh", "/bin/sh", "-c", cmd, NULL); 
    system(cmd.c_str()); 

    /*When system call it generate console output like : your job submitted */ 
    /* redirect to file */ 
    exit(-1); 
    } 

    if (pid > 0) 
    return pid; 

    cout<<" child is done"<<endl; 
    return 0; 
} 
+2

Рассмотрите возможность фиксации кода в вашем вопросе. Кстати, вы бы избежали этого беспорядка, если бы вы использовали опцию «использование пробелов вместо вкладок» вашего редактора ... – hyde

+1

Кажется, вы должны использовать 'dup2' _before_ для записи в stdout. –

+0

Я не получил you.it уже создавал файл processid.stdout, который мне нужно прочитать – user765443

ответ

1

Это не совсем ясно, что ваше мышление здесь - ваш код появляется раскошелиться ребенком, который делает кучу фантазии И.О. вещей, чтобы попытаться перенаправить ваши приложения стандартный вывод к файл, а затем запускает команду с помощью system(). Команда в вашем коде имеет свои собственные переадресации, в частности через «-o», поэтому, вероятно, она не записывает в stdout.

В родительском процессе вы пытаетесь открыть для чтения тот же файл, который ваш дочерний процесс откроет для записи. У вас нет синхронизации, поэтому они могут произойти в любом порядке. Кажется, вы пытаетесь использовать «cat» для чтения файла и попытки прочитать stdout кошки?

То, что я думаю, что вы на самом деле пытается сделать это эквивалент C/C++ из в Perl

$foo = `ls -l /tmp`; 

или что-то подобное - выполнить команду и захватить выход.

Лучший способ сделать это - использовать трубы.

#include <iostream> 
#include <fcntl.h> 
#include <stdio.h> 
#include <unistd.h> 

enum { WritePipe = 1, ReadPipe = 0 }; 

int main(int argc, const char** argv) 
{ 
    int pipes[2]; // each process is going to have its own file descriptor. 
    if(pipe(pipes) != 0) { 
     perror("pipe failed"); 
     return -1; 
    } 

    pid_t pid = fork(); 
    if(pid == 0) { 
     // child 
     close(pipes[ReadPipe]); // close the parent pipe in our context. 

     // redirect stdout and stderr to the pipe. 
     dup2(pipes[WritePipe], STDOUT_FILENO); 
        dup2(pipes[WritePipe], STDERR_FILENO); 
        // close(STDERR_FILENO); // <- or just do this to close stderr. 

     int result = system("ls -ltr /etc"); 
     close(pipes[WritePipe]); 
     return result; 
    } 

    if(pid < 0) { 
     perror("fork failed"); 
     return -1; 
    } 

    // Parent process has launched the child. 
    close(pipes[WritePipe]); 

    char buffer[4097]; 
    int bytesRead; 
    while((bytesRead = read(pipes[ReadPipe], buffer, sizeof(buffer) - 1)) > 0) { 
     buffer[bytesRead] = 0; 
     std::cout << buffer; 
    } 
    std::cout << std::endl; 

    close(pipes[ReadPipe]); 

    return 0; 
} 
Смежные вопросы