10

shell 命令将$ avrdude -c usbtiny文本输出到标准错误。我无法使用诸如 head-less-more 之类的命令来阅读它,因为它不是标准输出。我想要文本到标准输出或文件。我怎样才能在C中做到这一点?我试图通过我的最后一个问题来解决问题,但仍未解决。

4

4 回答 4

23

我没有在 OpenBSD 中尝试过类似的操作,但至少在一些 *nix 类系统中,您可以使用dup2.

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

int main(void) {  

  fprintf(stderr, "This goes to stderr\n");

  dup2(1, 2);  //redirects stderr to stdout below this line.

  fprintf(stderr, "This goes to stdout\n");
}
于 2010-06-11T01:56:41.530 回答
3

正常的方式是这样的:

avrdude -c usbtiny 2>&1

这指示通常会转到 stderr 的内容改为转到 stdout。如果您希望将其定向到文件,则可以执行以下操作:

avrdude -c usbtiny 2> outputfile.txt
于 2010-06-11T01:28:19.220 回答
0

下面使用POSIX函数将标准输出文件号复制成标准错误文件号。POSIX 页面中给出了将 stderr 复制到 stdoutdup2作为该函数的示例用法。

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

int main (void)
{
    pid_t child = fork();

    if (child == 0)
    {
        dup2(STDOUT_FILENO, STDERR_FILENO);
        execlp("avrdude", "-c", "usbtiny", NULL);
    }
    else if (child > 0)
    {
        waitpid(child);
        puts("Done!");
    }
    else
    {
        puts("Error in forking :(");
    }

    return 0;
}
于 2010-06-11T02:05:40.017 回答
0

我需要以某种方式阻止 C 中的命令,以便获得它的 stderr

从阅读开始man forkman exec了解如何启动子进程。调查man 7 signalman sigaction以及man wait如何收割孩子。

最后,man dup2.

未经测试的代码来举例说明:

int pip_stderr[2];
int r;
int pid;

r = pipe(pip_stderr);
assert( r != -1 );

int pid = fork();
assert( pid != -1 );
if (pid == 0) { /* child */
   /* child doesn't need to read from stderr */
   r = close(pip_stderr[0]); assert( r != -1 );
   /* make fd 2 to be the writing end of the pipe */
   r = dup2(pip_stderr[1], 2); assert( r != -1 );
   /* close the now redundant writing end of the pipe */
   r = close(pip_stderr[1]); assert( r != -1 );
   /* fire! */
   exec( /* whatever */ );
   assert( !"exec failed!" );
} else { /* parent */
   /* must: close writing end of the pipe */
   r = close( pip_stderr[1] ); assert( r != -1 );

   /* here read from the pip_stderr[0] */

   r = waitpid(pid,0,0); assert( r == pid );
}

使用 dup2() 我们将孩子的 stderr(即 fd 2)替换为管道的写入端。pipe() 在 fork() 之前调用。在 fork 之后,我们还必须关闭管道的所有悬挂端,以便父进程中的读取实际上会收到 EOF。

可能有一个使用 stdio 的更简单的解决方案,但我不知道。由于 popen() 通过 shell 运行命令,可能有人可以告诉它将 stderr 重定向到 stdout(并将 stdout 发送到 /dev/null)。从来没有试过。

也可以使用 mktemp() ( man 3 mktemp) 创建一个临时文件名,为 system() 编写命令将命令的 stderr 重定向到临时文件,并在 system() 返回后读取临时文件。

于 2010-06-11T02:13:57.240 回答