【问题标题】:How to catch the ouput from a execl command如何捕获excel命令的输出
【发布时间】:2010-12-19 02:20:31
【问题描述】:

我正在使用execl 函数从 C 中运行 Linux 进程。当我这样做时,例如:

int cmd_quem() { 
  int result; 
  result = fork();
  if(result < 0) {
    exit(-1);
  }

  if (result == 0) {
    execl("/usr/bin/who", "who", NULL);
    sleep(4); //checking if father is being polite 
    exit(1); 
  } 
  else { 
    // father's time
    wait();
  }

  return 0;
}

我在控制台上得到了在终端上执行“谁”的结果。我想知道是否有任何功能可以“捕获”命令的输出结果。我的意思是,如果有的话可以抓住这个:

feuplive tty5         2009-11-21 18:20

这是 who 命令产生的行之一。

【问题讨论】:

    标签: c linux subprocess


    【解决方案1】:

    为此,您需要打开一个管道。然后,您用管道的写入端替换孩子的标准输出,并从父管道的读取端读取。就像你的代码的这个修改版本:

    int cmd_quem(void) {
      int result;
      int pipefd[2];
      FILE *cmd_output;
      char buf[1024];
      int status;
    
      result = pipe(pipefd);
      if (result < 0) {
        perror("pipe");
        exit(-1);
      }
    
      result = fork();
      if(result < 0) {
        exit(-1);
      }
    
      if (result == 0) {
        dup2(pipefd[1], STDOUT_FILENO); /* Duplicate writing end to stdout */
        close(pipefd[0]);
        close(pipefd[1]);
    
        execl("/usr/bin/who", "who", NULL);
        _exit(1);
      }
    
      /* Parent process */
      close(pipefd[1]); /* Close writing end of pipe */
    
      cmd_output = fdopen(pipefd[0], "r");
    
      if (fgets(buf, sizeof buf, cmd_output)) {
        printf("Data from who command: %s\n", buf);
      } else {
        printf("No data received.\n");
      }
    
      wait(&status);
      printf("Child exit status = %d\n", status);
    
      return 0;
    }
    

    【讨论】:

    • 正确清理管道的工作做得很好 - 很少有人能做到这一点。
    • 我做到了,但只有当我切换线路 wait() 并将其放在 fgets() 之前,它才能完全工作,有什么解释吗?
    • @mf_:这应该没什么区别——你用的是什么操作系统?
    • @caf ubuntu 10.04LTS,但现在有点道理,即使只有几个字节,父亲也会捕获缓冲区中的内容,而如果我们 wait() 让儿子完全完成缓冲区将拥有一切,这是我的解释,如果你愿意,我可以发布我对这件作品的调整版
    • @mf_: fgets() 应该读取到换行符或文件结尾,如果子进程没有输出换行符或退出,它不应该只读取“几个字节”。
    【解决方案2】:

    首先,execl 不会返回,除非出现诸如找不到可执行文件之类的问题。 sleep(4) 可能永远不会被执行。

    至于重定向和获取输出,请查看Unix Programming FAQ。寻找spawn_background_command

    【讨论】:

      【解决方案3】:

      exec() 系列函数从一个常规的可执行文件创建一个新的进程映像。这个文件要么是一个可执行的目标文件,要么是一个解释器脚本。成功调用 exec() 函数不会返回任何结果,因为调用进程在功能上已被新进程替换。

      因此,除非失败,否则 exec() 之后的任何代码都不会执行。

      如果你想捕获 shell 命令的输出,你需要popen

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-01
        • 1970-01-01
        • 2017-02-26
        • 2013-01-16
        • 1970-01-01
        • 2012-11-22
        • 2012-06-29
        • 1970-01-01
        相关资源
        最近更新 更多