为什么不能从尾-f数据? [英] Why can't get data from tail -f?

查看:206
本文介绍了为什么不能从尾-f数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的计划,我重定向子进程的输出管道,并在父母得到这个结果,并做一些事情(这并不重要)。但是,当我使用尾我的程序不能正常工作-f test.txt的命令,不会收到尾中的任何数据运行,并且只有在得到这个数据尾部结束(或死亡)。

起初我还以为问题是,尾-f 不冲水,这就是为什么没有数据我会接受,但是当我试图重定向输出尾-f 来的一些文件中的数据均即使尾巴还没说完这个文件。

  //创建子和重定向数据code(重要部分)
//唯一的核心就在这里,所以请不要告诉我,也许管道()或fork()失败将为pid_t PID;
INT outpipe [2]; //从标准输出管道读取
INT errpipe [2]; //从标准错误读取管// Createing对孩子的输出和错误流管
管(outpipe);
管(errpipe);
PID =叉();
如果(PID == 0)
{
    //这是子进程。关闭管道的读端和复制输出和错误流
    关闭(outpipe [0]);
    dup2(outpipe [1],STDOUT_FILENO);
    关闭(errpipe [0]);
    dup2(errpipe [1],STDERR_FILENO);    如果(execvp(的argv [0],(char * const的*)的argv)== -1)
    {
        fprintf中(标准错误,无法执行命令%S:%S的argv [0],字符串错误(错误));
        _exit(EXIT_FAILURE);
    }    _exit(EXIT_SUCCESS);
}
否则如果(PID!= -1)
{
    //这是父进程,关闭管道的写端和打开FDS为FILE
    关闭(outpipe [1]);
    * child_stdout_stream = fdopen(outpipe [0],RT);
    关闭(errpipe [1]);
    * child_stderr_stream = fdopen(errpipe [0],RT);
    * child_pid = PID;
}

然后我从阅读 child_stderr_stream child_stdout_stream 这是作为参数的功能上面的部分是由通过什么。
对于读书,我使用select(),以不阻塞程序,直到从流的一个读数。


添加的选择部分和阅读

  INT select_and_read(FILE **文件,BOOL * is_eof,字符*字符,为int *口罩,诠释NFILES,INT超时,将为pid_t child_pid)
{
    INT max_fd_plus_1 = 0;
    FD_SET RFDS;
    timeval结构电视;    FD_ZERO(安培; RFDS);    的for(int i = 0; I< NFILES ++ I)
    {
        如果(is_eof [I] == FALSE)
        {
            FD_SET(的fileno(文件[I]),放大器; RFDS);
            max_fd_plus_1 =(max_fd_plus_1>的fileno(文件[I]))? max_fd_plus_1:的fileno(文件[I]);
        }
    }
    ++ max_fd_plus_1;    tv.tv_sec =超时/ 1000;
    tv.tv_usec =(超时%1000)* 1000;    INT RETVAL =选择(max_fd_plus_1,&安培; RFDS,NULL,NULL,&安培;电视);
    如果(RETVAL大于0)
    {
        *掩模= 0;
        的for(int i = 0; I< NFILES ++ I)
        {
            如果(is_eof [I] == FALSE)
            {
                如果(FD_ISSET(的fileno(文件[I]),放大器; RFDS))
                {
                    *口罩| = 1<<一世;
                    字符由[i] =龟etc(文件[I]);
                }
            }
        }
    }
    其他
    {
        杀(child_pid,SIGKILL);
    }
    返回RETVAL;
}


解决方案

这个奇怪的问题已经解决非常奇怪。我的文件只需设置缓冲区0是这样的:

 否则如果(PID!= -1)
{
    //这是父进程,关闭管道的写端和打开FDS为FILE
    关闭(outpipe [1]);
    * child_stdout_stream = fdopen(outpipe [0],RT);
则setbuf(* child_stdout_stream,NULL);
    关闭(errpipe [1]);
    * child_stderr_stream = fdopen(errpipe [0],RT);
则setbuf(* child_stderr_stream,NULL);
    * child_pid = PID;
}

这是很奇怪的,这会有所帮助,但在任何情况下,我的计划是目前运作良好。

In my program I'm redirecting output of child process to pipe and in parent getting this result and doing something (this is not important). But my program doesn't work when I'm using tail -f test.txt command and doesn't recieve any data during tail is running, and getting this data only after tail is finished (or killed).

At first I have thought that problem was that tail -f doesn't flushing and that's why no data I can recieve, but when I have tried to redirect output of tail -f to some file the data were in this file even when tail were not finished.

//the code of creating child and redirecting data (important part)
//only core is here so please don't tell me that maybe pipe() or fork() is failed

pid_t pid;
int outpipe[2]; //pipe for reading from stdout
int errpipe[2]; //pipe for reading from stderr

// Createing pipes for childs stdout and stderr streams
pipe(outpipe);
pipe(errpipe);
pid = fork();
if(pid == 0)
{
    // This is the child process. Closing read end of pipes and duplicating stdout and stderr streams
    close(outpipe[0]);
    dup2(outpipe[1], STDOUT_FILENO);
    close(errpipe[0]);
    dup2(errpipe[1], STDERR_FILENO);

    if(execvp(argv[0], (char * const *)argv) == -1)
    {
        fprintf(stderr, "Failed to execute command %s: %s", argv[0], strerror(errno));
        _exit(EXIT_FAILURE);
    }

    _exit(EXIT_SUCCESS);
}
else if (pid != -1)
{
    // This is the parent process, Closing write end of pipes and opening fds as FILE
    close(outpipe[1]);
    *child_stdout_stream=fdopen(outpipe[0], "rt");
    close(errpipe[1]);
    *child_stderr_stream=fdopen(errpipe[0], "rt");
    *child_pid=pid;
}

Then I'm reading from child_stderr_stream and child_stdout_stream which were passed as parameters to function the part above is from what. For reading I'm using select() to not block program until reading from one of the streams.


Adding part of select and read

int select_and_read(FILE **files, bool *is_eof, char *chars, int *mask, int nfiles, int timeout, pid_t child_pid)
{
    int max_fd_plus_1 = 0;
    fd_set rfds;
    struct timeval tv;

    FD_ZERO(&rfds);

    for(int i = 0; i < nfiles; ++i)
    {
        if(is_eof[i]==false)
        {
            FD_SET(fileno(files[i]), &rfds);
            max_fd_plus_1 = (max_fd_plus_1 > fileno(files[i])) ? max_fd_plus_1 : fileno(files[i]);
        }
    }
    ++max_fd_plus_1;

    tv.tv_sec = timeout / 1000;
    tv.tv_usec = (timeout % 1000) * 1000;

    int retval = select(max_fd_plus_1, &rfds, NULL, NULL, &tv);
    if(retval > 0)
    {
        *mask = 0;
        for(int i = 0; i < nfiles; ++i)
        {
            if(is_eof[i]==false)
            {
                if(FD_ISSET(fileno(files[i]), &rfds))
                {
                    *mask |= 1 << i;
                    chars[i] = fgetc(files[i]);
                }
            }
        }
    }
    else
    {
        kill(child_pid, SIGKILL);
    }
    return retval;
}

解决方案

This strange problem have been solved very strangely. I have just set buffers of files to 0 this way:

else if (pid != -1)
{
    // This is the parent process, Closing write end of pipes and opening fds as FILE
    close(outpipe[1]);
    *child_stdout_stream=fdopen(outpipe[0], "rt");
setbuf(*child_stdout_stream, NULL);
    close(errpipe[1]);
    *child_stderr_stream=fdopen(errpipe[0], "rt");
setbuf(*child_stderr_stream, NULL);
    *child_pid=pid;
}

This is very strange, that this helps, but in any case my program is now working well.

这篇关于为什么不能从尾-f数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆