以最佳方式从 system() 命令捕获标准输出
我正在尝试通过 system()
启动外部应用程序 - 例如 system("ls")
。 我想在它发生时捕获它的输出,以便我可以将其发送到另一个函数以进行进一步处理。 在 C/C++ 中做到这一点的最佳方法是什么?
I'm trying to start an external application through system()
- for example, system("ls")
. I would like to capture its output as it happens so I can send it to another function for further processing. What's the best way to do that in C/C++?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
来自 popen 手册:
From the popen manual:
尝试 popen() 函数。 它执行一个命令,如 system(),但将输出定向到一个新文件中。 返回指向流的指针。
Try the popen() function. It executes a command, like system(), but directs the output into a new file. A pointer to the stream is returned.
编辑:误读问题为想要将输出传递给另一个程序,而不是另一个函数。 popen() 几乎肯定是您想要的。
系统为您提供了对 shell 的完全访问权限。 如果您想继续使用它,您可以
通过 system("ls > tempfile.txt") 将其输出重定向到临时文件,但是选择一个安全的临时文件很痛苦。 或者,您甚至可以通过另一个程序重定向它: system("ls | otherprogram");
有些人可能会推荐 popen() 命令。 如果您可以自己处理输出,这就是您想要的:
这将为您提供一个 FILE 指针,您可以从中读取命令的输出。
您还可以使用 pipeline() 调用来创建连接,结合 fork() 创建新进程,使用 dup2() 更改它们的标准输入和输出,使用 exec() 运行新程序,使用 wait()在主程序中等待他们。 这只是像 shell 一样设置管道。 有关详细信息和示例,请参阅 pipeline() 手册页。
EDIT: misread question as wanting to pass output to another program, not another function. popen() is almost certainly what you want.
System gives you full access to the shell. If you want to continue using it, you can
redirect it's output to a temporary file, by system("ls > tempfile.txt"), but choosing a secure temporary file is a pain. Or, you can even redirect it through another program: system("ls | otherprogram");
Some may recommend the popen() command. This is what you want if you can process the output yourself:
which will give you a FILE pointer you can read from with the command's output on it.
You can also use the pipe() call to create a connection in combination with fork() to create new processes, dup2() to change the standard input and output of them, exec() to run the new programs, and wait() in the main program to wait for them. This is just setting up the pipeline much like the shell would. See the pipe() man page for details and an example.
函数
popen()
和pclose()
可能就是您正在寻找的。查看 glibc 手册< /a> 为例。
The functions
popen()
andpclose()
could be what you're looking for.Take a look at the glibc manual for an example.
在 Windows 中,不使用 system(),而是使用 CreateProcess,将输出重定向到管道并连接到管道。
我猜这也可以通过某种 POSIX 方式实现?
In Windows, instead of using system(), use CreateProcess, redirect the output to a pipe and connect to the pipe.
I'm guessing this is also possible in some POSIX way?
在此页面中: capture_the_output_of_a_child_process_in_c 描述了使用 popen 与使用 fork/exec 的局限性/dup2/STDOUT_FILENO 方法。
我在 捕获 tshark 输出时遇到问题波彭。
我猜这个限制可能是我的问题:
如果我有其他方法的解决方案,我会回到这个答案。
In this page: capture_the_output_of_a_child_process_in_c describes the limitations of using popen vs. using fork/exec/dup2/STDOUT_FILENO approach.
I'm having problems capturing tshark output with popen.
And I'm guessing that this limitation might be my problem:
I'll come back to this answer if I have a solution with the other approach.
我不完全确定它在标准 C 中是否可能,因为两个不同的进程通常不共享内存空间。 我能想到的最简单的方法是将第二个程序将其输出重定向到文本文件(程序名> textfile.txt),然后读回该文本文件进行处理。 然而,这可能不是最好的方法。
I'm not entirely certain that its possible in standard C, as two different processes don't typically share memory space. The simplest way I can think of to do it would be to have the second program redirect its output to a text file (programname > textfile.txt) and then read that text file back in for processing. However, that may not be the best way.
其实我刚刚查了一下,:
popen 是有问题的,因为进程是 fork 的。 因此,如果您需要等待 shell 命令执行,那么您就有错过它的危险。 就我而言,我的程序甚至在管道开始工作之前就关闭了。
我最终在 Linux 上使用了带有 tar 命令的系统调用。 system 的返回值是 tar 的结果。
所以:如果你需要返回值,那么不仅不需要使用popen,它可能不会做你想要的。
Actually, I just checked, and:
popen is problematic, because the process is forked. So if you need to wait for the shell command to execute, then you're in danger of missing it. In my case, my program closed even before the pipe got to do it's work.
I ended up using system call with tar command on linux. The return value from system was the result of tar.
So: if you need the return value, then not no only is there no need to use popen, it probably won't do what you want.
最有效的方法是直接使用
stdout
文件描述符,绕过FILE
流:要从 child 读取输出,请使用
popen2()< /code> 像这样:
写入和读取:
The most efficient way is to use
stdout
file descriptor directly, bypassingFILE
stream:To read output from child use
popen2()
like this:To both write and read:
函数
popen()
等不会重定向 stderr 等; 为此,我编写了popen3()
。这是我的 popen3() 的鲍德勒版本:
The functions
popen()
and such don't redirect stderr and such; I wrotepopen3()
for that purpose.Here's a bowdlerised version of my popen3():