微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何从popen&fgets获取无缓冲的输出

如何解决如何从popen&fgets获取无缓冲的输出

我正在使用popen执行命令并读取输出。我将文件描述符设置为非阻塞模式,以便可以设置自己的超时,如下所示:

    auto stream = popen(cmd.c_str(),"r");

    int fd = fileno(stream);
    int flags = fcntl(fd,F_GETFL,0);
    flags |= O_NONBLOCK;
    fcntl(fd,F_SETFL,flags);

    while(!feof(stream)) {
        if(fgets(buffer,MAX_BUF,stream) != NULL) {
            // do something with buffer...
        }
        sleep(10);
    }
    pclose(stream);

除了fgets一直返回NULL,直到程序执行完毕,然后按预期方式返回所有输出外,此方法效果还不错。

换句话说,即使程序立即向标准输出输出一些文本和换行符,我的循环也不会立即读取它。以后才看到。

popen的文档中,我看到:

请注意,认情况下,输出popen()流是块缓冲的。

我已经尝试了一些方法关闭缓冲(例如setvbuf(stream,NULL,_IONBF,0)),但到目前为止还算不上运气。

如何关闭缓冲以便可以实时读取输出

谢谢!

解决方法

基于select()之类的解决方案将更加准确和灵活。试试这个:

    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/select.h>


    void read_cmd(const char *cmd)
    {
    FILE *stream;
    int fd;
    int flags;
    char buffer[1024];
    fd_set fdset;
    struct timeval timeout;
    int rc;
    int eof;

      stream = popen(cmd,"r");

      fd = fileno(stream);

      eof = 0;
      while(!eof) {

        timeout.tv_sec = 10; // 10 seconds
        timeout.tv_usec = 0;

        FD_ZERO(&fdset);
        FD_SET(fd,&fdset);

        rc = select(fd + 1,&fdset,&timeout);

        switch(rc) {

          case -1: {
            // Error
            if (errno != EINTR) {
              fprintf(stderr,"select(): error '%m' (%d)\n",errno);
            }
            return;
          }
          break;

          case 0: {
            // Timeout
            printf("Timeout\n");
          }
          break;

          case 1: {
            // Something to read
            rc = read(fd,buffer,sizeof(buffer) - 1);
            if (rc > 0) {
              buffer[rc] = '\0';
              printf("%s",buffer);
              fflush(stdout);
            }

            if (rc < 0) {
              fprintf(stderr,"read(): error '%m' (%d)\n",errno);
              eof = 1;
            }

            if (0 == rc) {
              // End of file
              eof = 1;
            }

          }
          break;

        } // End switch

      } // End while

      pclose(stream);

    }

    int main(int ac,char *av[])
    {

      read_cmd(av[1]);

      return 0;

    } // main

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。