【问题标题】:redirecting output to a file in C将输出重定向到C中的文件
【发布时间】:2011-12-15 07:57:05
【问题描述】:

我用 C 编写了一个用于执行基本命令的基本 shell,它将执行命令 lsls -alls -al | more 等。

我想在我的 shell 中执行以下命令。 喜欢;

ls -al > a.txt

这会给我a.txt 文件,其中包含ls -al 进程的输出。 我找到了一个解决方案,它正在更改我的 shell 中的命令,例如 [command1] | tee [filename]。在这种情况下,它会将ls -al > a.txt 更改为ls -al | tee a.txt。但是这个过程也将输出提供给文件和终端。如何在终端中停止打印输出。

或者有没有比使用 tee 命令更好的解决方案。 提前谢谢...

【问题讨论】:

  • 为什么| 输出重定向符号在你的shell 中有效,而> 却不行?

标签: linux shell


【解决方案1】:

这是我用 dup2 测试的结果

更微妙的一点是在正确的时间记住 fflush :) 否则,你会得到非常令人惊讶的结果。

另外,更喜欢 fileno 而不是硬编码 1 (stdout) 2 (stderr)。

重定向stdin 留给读者作为练习

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

int main(int argc, const char *argv[])
{
    int out = open("cout.log", O_RDWR|O_CREAT|O_APPEND, 0600);
    if (-1 == out) { perror("opening cout.log"); return 255; }

    int err = open("cerr.log", O_RDWR|O_CREAT|O_APPEND, 0600);
    if (-1 == err) { perror("opening cerr.log"); return 255; }

    int save_out = dup(fileno(stdout));
    int save_err = dup(fileno(stderr));

    if (-1 == dup2(out, fileno(stdout))) { perror("cannot redirect stdout"); return 255; }
    if (-1 == dup2(err, fileno(stderr))) { perror("cannot redirect stderr"); return 255; }

    puts("doing an ls or something now");

    fflush(stdout); close(out);
    fflush(stderr); close(err);

    dup2(save_out, fileno(stdout));
    dup2(save_err, fileno(stderr));

    close(save_out);
    close(save_err);

    puts("back to normal output");

    return 0;
}

【讨论】:

  • 一件事,如果文件存在,shell会将数据覆盖到文件中,否则它将创建,那么如何覆盖它
  • @Zeemaan:使用O_WRONLY|O_CREAT|O_TRUNC 应该可以工作(或creat("cout.log", 0600) 而不是打开)。见opencreat
  • fflush(stdout);打印文件里面的东西,意味着输出也复制到标准输出。使用 fflush 重要吗?
  • @Zeemaan:我怀疑你这样做的顺序不对。如我的回答所示,您需要在重新分配输出流之前刷新。是的,我强烈建议使用fflush(通常流是行缓冲的,所以如果你只写完整的行,例如puts,差别不大。但这是一个很大的“如果”)跨度>
  • 这很好:)。但是如果我想将 stdout 和 stderr 都重定向到同一个日志文件呢???
【解决方案2】:

当输出到文件时不要使用管道。

当你 fork 子进程运行ls 命令时,你注意到重定向,然后打开文件;然后您使用dup2()(或close()dup()),以便文件描述符现在是孩子的标准输出;你关闭了重复的文件描述符——open() 返回的那个;然后像往常一样执行ls;它的标准输出现在被发送到文件中。

请注意,您在分叉之后而不是之前执行非管道 I/O 重定向。管道必须在分叉之前设置,但其他 I/O 重定向不需要。

【讨论】:

    【解决方案3】:

    在新创建的进程中调用execve(2)执行命令之前,可以通过dup2(2)系统调用重定向其标准输入或输出:

    /* redirect stdout to a file */
    dup2(1, some_open_file_descriptor);
    

    当然,您需要进行一些错误处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      • 2016-08-09
      • 2013-10-11
      • 2023-03-19
      相关资源
      最近更新 更多