![如果您想获取被调用命令的输出,在 C++ 中运行子进程的最佳方法](https://linux22.com/image/205019/%E5%A6%82%E6%9E%9C%E6%82%A8%E6%83%B3%E8%8E%B7%E5%8F%96%E8%A2%AB%E8%B0%83%E7%94%A8%E5%91%BD%E4%BB%A4%E7%9A%84%E8%BE%93%E5%87%BA%EF%BC%8C%E5%9C%A8%20C%2B%2B%20%E4%B8%AD%E8%BF%90%E8%A1%8C%E5%AD%90%E8%BF%9B%E7%A8%8B%E7%9A%84%E6%9C%80%E4%BD%B3%E6%96%B9%E6%B3%95.png)
我正在用 C++ 编写一个应用程序。在我的代码中的许多地方,我使用system()
函数来运行一些命令。我不确定这是一个优雅的解决方案,我想用另一种调用子进程的方式来替换使用此函数。
有两个重要问题需要考虑。
- 首先,我想等待该子进程执行结束并检查其返回码。
- 其次,有时这些命令会在终端中打印一些重要信息。我希望这些信息能够被 读取和存储
rsyslog
。我正在使用 记录我的应用程序中的一些事件syslog(LOG_INFO, "%s", "Some event occured.")
。是否可以以类似的方式记录子进程的输出?
答案1
在我的代码中的许多地方,我使用
system()
函数来运行一些命令。
这不是一个好兆头!system
确实是你应该经常使用的东西 – 它不是一个 C++ 函数,它不是一个系统调用,它是一个打开 shell 来执行命令的 C 库(好吧,它被包装在 中<cstdlib>
,但仍然) – 不仅是这个很多在大多数情况下,这不仅是一种开销,也是在程序中引入安全漏洞的常见方法。它的行为也可能非常令人惊讶——您的环境可能使 shell 的行为变得有趣。
所以,不要使用,system
除非你真的想要
- 找到/bin/sh程序
- 运行 ,
- 将其参数 (
argv
) 设置为-c
what you passed to system()
仅当您执行的不仅仅是其他可执行文件,而是其他可执行文件时,第 3 点才有意义外壳命令,即首先可以逻辑地合并到您的程序中的东西。
我不确定这是一个优雅的解决方案,我想用另一种调用子进程的方式来替换使用此函数。
当然有几种方法,您真正应该做什么实际上取决于您打电话的内容以及原因和频率。
首先,我想等待该子进程执行结束并检查其返回码。
system
顺便说一句,您也可以使用 来做到这一点WEXITSTATUS
。有关更多详细信息,请参阅 man 2 waitpid
。无论如何,如上所述,我不鼓励使用system
.
有时这些命令会在终端中打印一些重要信息。我希望 rsyslog 能够读取并存储这些信息。
不是说显而易见的事情,但也许这些命令应该自己记录日志?
无论如何,如果您想捕获您生成的进程的输出,请使用 libc/posix popen
。
再次,我仍然强烈建议您研究一下这样的问题:您通过调用外部命令所做的事情是否可以通过现有的库来完成,这样您就不必通过要求操作系统来完成稍微尴尬的绕道运行另一个进程并与其通信。
答案2
我无法检查 C++ 的情况,但 @Marcus 回答说这popen()
是可用的。这将为您的应用程序提供一个FILE *
对象,您可以在其中读取stdout
所调用命令的内容。
还有一个独立命令logger
将其标准输入发送到系统日志。
它恰好popen
通过调用运行命令行/bin/sh
,因此您可以调用应用程序的 stderr 到记录器管道的重定向。这可能意味着您需要包装命令才能使用 Bash 进程替换。所以你的 popen 命令可能类似于(未经测试):
fp = popen ("bash -c 'myApp myArgs 2>( logger -opts )'", "r");