C:如何将 stderr 从系统命令重定向到 stdout 或文件?

发布于 2024-09-04 19:26:10 字数 237 浏览 8 评论 0原文

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

The shell command $ avrdude -c usbtiny outputs text to stderr. I cannot read it with commmands such as head-less-more cos it is not stdout. I want the text to stdout or to a file. How can I do it in C? I have tried to solve the problem by my last question but still unsolved.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无尽的现实 2024-09-11 19:26:11

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

通过阅读 man forkman exec 了解如何启动子进程来获取其 stderr Start。查看 man 7 signalman sigactionman 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)替换为管道的写入端。 pipeline() 在 fork() 之前调用。在 fork 之后,我们还必须关闭管道的所有悬挂端,以便父进程中的读取实际上会收到 EOF。

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

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

I need to somehow block the command in C so I can get its stderr

Start by reading man fork, man exec on how to start a child process. Look into man 7 signal, man sigaction and man wait for how to reap the child.

Finally, the man dup2.

Untested code to exemplify:

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 );
}

Using dup2() we replace stderr (which is fd 2) of the child with a writing end of a pipe. pipe() is called before fork(). After fork we also have to close all hanging ends of the pipe so that the reading in parent process would actually receive EOF.

Probably there is a simpler solution using stdio, but I'm not aware of it. Since popen() runs the command via shell, probably one can tell it to redirect stderr to stdout (and send stdout to /dev/null). Never tried that.

One can also use mktemp() (man 3 mktemp) to create a temp file name, compose command for system() to redirect stderr of the command to the temp file and after system() returns read the temp file.

德意的啸 2024-09-11 19:26:10

我还没有在 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");
}

I've not tried something like this in OpenBSD, but in at least a few *nix-like systems, you can do this using 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");
}
春夜浅 2024-09-11 19:26:10

正常的方式是这样的:

avrdude -c usbtiny 2>&1

这将通常进入 stderr 的内容引导到 stdout 。如果您希望将其定向到文件,您可以执行以下操作:

avrdude -c usbtiny 2> outputfile.txt

The normal way would be something like:

avrdude -c usbtiny 2>&1

This directs what would normally go to stderr to go to stdout instead. If you'd prefer to direct it to a file, you could do something like:

avrdude -c usbtiny 2> outputfile.txt
久隐师 2024-09-11 19:26:10

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

#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;
}

The following uses the POSIX function to duplicate the standard output file number into the standard error file number. Duplicating stderr to stdout is given in the POSIX page for dup2 as an example usage of the function.

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文