【问题标题】:How to redirect the output of system() to a file?如何将 system() 的输出重定向到文件?
【发布时间】:2012-06-26 17:13:27
【问题描述】:

在这个C 程序中

#include <stdio.h>
#include <fcntl.h>
int main()
{
    int file = open("Result", O_CREAT|O_WRONLY, S_IRWXU);

    dup2(stdout, file);
    system("ls -l");

    return 0;
}

我正在尝试将system() 的输出重定向到一个文件,因为我使用了dup2,但它不起作用。

这段代码有什么问题
并且,请告诉我是否有更好的方法来做到这一点? (在终端不使用&gt;

【问题讨论】:

  • 为什么不在system 命令中使用&gt; 重定向?
  • 使用system("ls -l &gt; Result"); 或制作您自己的fork()/exec*() 组合。
  • 不要使用system。总是错的。在没有 shell 的情况下自己运行子进程,使用 forkexecvpposix_spawn
  • @R.. 这里,“它总是错的”意味着 system() 总是错的或者使用 system() 是错的。请澄清。
  • 我的意思是 system 应该被视为已弃用,因为 (1) 很难对它做任何有用的事情,并且 (2) 试图用它做任何有用的事情(例如传递参数)几乎肯定会产生危险(可能对安全至关重要)与 shell 转义相关的错误。

标签: c linux system stdout dup


【解决方案1】:

stdout 是标准输出流的FILE * 指针。 dup2 需要文件描述符,您也弄乱了参数顺序。 使用

dup2(file, 1);

改为。

在更好的方式做这部分。这种方式很糟糕,因为您可能希望在此 system 调用完成后恢复您的标准输出。您可以通过多种方式执行此操作。你可以在某处dup 它然后dup2 它回来(并关闭dupped 一个)。我个人不喜欢按照其他答案中的建议编写自己的 cat 实现。如果您唯一想要的是将带有 system 的单个 shell 命令重定向到文件系统中的文件,那么可能最直接和最简单的方法是构造 shell 命令来执行此操作

system("ls -l > Result");

但如果文件名(结果)来自用户输入,您必须小心,因为用户可以提供类似 'Result; rm -rf /*' 的文件名。

此外,关于安全性主题,您应该考虑按照 cmets 中的建议指定 ls 的完整路径:

system("/bin/ls -l > Result");

【讨论】:

  • 我编辑了您的帖子,在您的示例中包含了 ls 的绝对路径。
  • 恢复编辑,因为 OP 运行 "ls",这将改变系统调用的含义。该问题也与绝对或相对路径无关。我认为最好问问@unkulunkulu他是否想修改他的答案。
  • @Andomar,实际上,我接受了编辑,但无论如何,你的观点都是有效的,我看不出有什么区别:) Wug,谢谢你的建议,无论如何都会在 cmets 中看到.
  • @unkulunkulu:如果您同意 Wug,请不要犹豫撤销我的更改。您可以通过单击“已编辑 X 分钟前”并选择“恢复”来进行相应的修订。
  • 在不指定绝对路径的情况下调用系统通常是一个非常糟糕的主意,因为狡猾的人可能会通过玩 PATH 来破坏您的程序。对于初学者来说养成习惯不是一个好错误。因此,我的编辑。
【解决方案2】:

简单的事情是确实使用&gt;

#include <stdio.h>
int main()
{
    system("ls -l > /some/file");

    return 0;
}

另一种方法是使用popen(),类似于

   #include <stdio.h>
   #include <stdlib.h>
   main()
   {
           char *cmd = "ls -l";
           char buf[BUFSIZ];
           FILE *ptr, *file;

           file = fopen("/some/file", "w");
           if (!file) abort();
           if ((ptr = popen(cmd, "r")) != NULL) {
                   while (fgets(buf, BUFSIZ, ptr) != NULL)
                           fprintf(file, "%s", buf);
                   pclose(ptr);
           }
           fclose(file);
           return 0;
   }

【讨论】:

    【解决方案3】:

    您应该使用popen() 库函数并从返回的FILE * 中读取数据块并将它们写入您喜欢的任何输出文件。

    Reference.

    【讨论】:

      【解决方案4】:

      使用dup 而不是dup2dup 创建一个别名文件描述符,该值应始终是最小的可用文件描述符。

      new_fd = dup(file); - 在这个语句中,file 的值可能是3(因为stdin0stdout1stderr2)。所以new_fd 将是4

      如果您想将stdout 重定向到文件中。然后如下操作。

      close(stdout);
      new_fd = dup(file);
      

      现在 dup 将返回 1 作为 file 描述符的别名,因为我们关闭了 stdout 所以打开的文件描述符是 0,2,3 并且 1 是最小的可用文件描述符。

      如果您使用dup2 表示,dup2(file,1); - 这样做

      【讨论】:

      • 使用dup()而不是dup2()如果您不关心副本的放置位置。如果您关心,请使用dup2()——这就是它的明确目的!相反,如果您只是希望最好,就像这个答案一样,它会一直正常工作,直到有一天模式打破并且您不知道它为什么会失败。这些会导致一些加重的深夜调试会话,这可以通过从一开始就以正确的方式来避免。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-05
      • 1970-01-01
      • 1970-01-01
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      • 2010-09-29
      相关资源
      最近更新 更多