c - 将stderr重定向到c中的缓冲区

标签 c posix stderr

我已经查看了之前提出的问题。我想出了这段代码来获取 stderr 的当前值,将其重新定向到 buf 并重新分配 stderr。这是代码。

stderr 到 buff 的重定向没有发生。当我尝试执行代码时,我可以在屏幕上看到这一点:

     ls: cannot access system: No such file or directory
     hellow world
     error from buffer

源代码如下所示:

#include<stdio.h>
static int fd;
static fpos_t pos;
char *buf;

void closeerr()
{
    fflush(stderr);
    fgetpos(stderr, &pos);
    fd = dup(fileno(stderr));
    buf =(char *)calloc(sizeof(char *),1024);
    stderr = fmemopen(buf, sizeof(buf), "w");
}

void reverterr()
{
    fflush(stderr);
    dup2(fd, fileno(stderr));
    close(fd);
    clearerr(stderr);
    fsetpos(stderr, &pos);
}

void main()
{
    closeerr();
    printf("hellow world");
    system(" ls -l system"); // this is where I see the error msg
    printf("error from buffer %s",buf);
    reverterr();
}

此代码将 stdout(逻辑与重定向 stderr 相同)重定向到临时文件(下面建议的方法 1,尽管我没有 fork 并创建一个子进程来写入文件)

void switchStdout(const char *newStream)
{
  fflush(stdout);
  fgetpos(stdout, &pos);
  fd = dup(fileno(stdout));
  freopen(newStream, "w", stdout);

}

void revertStdout()
 {
  fflush(stdout);
  dup2(fd, fileno(stdout));
  close(fd);
  clearerr(stdout);
  fsetpos(stdout, &pos);
 }

void main(){
  switchStdout("/tmp/err.txt");
  printf("Hello world");
  revertStdout();
}

最佳答案

fmemopen() 函数实际上并不打开文件描述符,因此 fileno() 位于从 fmemopen 获取的 FILE 上() 返回未定义的值。 fmemopen() 是通过直接写入缓冲区来实现的,而无需通过操作系统发送数据。无法通过 fork() 保留使用 fmemopen() 打开的文件。

另一个问题是您从不为缓冲区分配内存,请阅读 fmemopen() API 以及如何使用它来理解问题。

以下是两种有效的方法:

  • 打开一个临时文件,然后fork()。在 fork 进程中,将其文件描述符复制到文件描述符 2 (STDERR_FILENO) 上,然后执行您的命令。在父级中,为子级调用 wait(),然后读取其写入临时文件的内容。请注意,您需要在读取之前执行 lseek(),因为子进程会更改文件指针。
  • 使用pipe()打开fifo,然后使用fork()。在子进程中,将写入端复制到文件描述符 2 上,关闭读取端,然后执行命令。在父进程中,关闭写入端,并在子进程运行时从读取端读取子进程写入的内容。之后不要忘记为子进程wait()

关于c - 将stderr重定向到c中的缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36304597/

相关文章:

java - 如何阻止 Java/Eclipse 将 stdout 和 stderr 混合在一起?

c - 如何使用c程序删除注释

c - 使用 POSIX 定时器后程序不退出

c - 使用信号量解决哲学家就餐僵局

ubuntu - Cygwin/Red Hat 相当于 Debian 的 manpages-dev、manpages-posix-dev 的是什么?

process - 如何在 Rust 中将线程提升为子进程?

mysql - 无法在 CentOS 上使用 MariaDB 编译 C 程序

c++ - 如何使用 Directory.GetFiles

c - 使用 scanf 获取字符串来创建并针对 while 循环验证它...继续获取

windows - 如何在 Windows/DOS 上捕获 stderr?