从bash脚本返回输出到调用c++函数
Returning output from bash script to calling C++ function
我正在写一个婴儿程序练习。我试图完成的基本上是一个简单的小GUI显示服务(Linux);有启动、停止、启用和禁用服务的按钮(很像Windows中的msconfig应用程序"服务"选项卡)。我在Fedora 21上使用c++和Qt Creator。
我想用c++创建GUI,并通过调用bash脚本来用服务列表填充GUI,并在单击按钮时调用bash脚本来执行适当的操作(启用,禁用等)
但是当c++ GUI调用bash脚本(使用system("path/to/script.sh")
)时,返回值仅用于退出成功。我如何接收脚本本身的输出,以便我可以反过来使用它在GUI上显示?
举个概念性的例子:如果我想把(systemctl --type service | cut -d " " -f 1
)的输出显示到我用c++创建的GUI中,我该怎么做呢?这是我想要完成的事情的正确方法吗?如果没有,
- 什么是正确的方式?和
- 是否还有一种方法可以使用我当前的方法?
我已经找到了解决这个问题的方法,但我找不到关于如何从 Bash 到 c++返回值的信息,只有如何从c++调用 Bash脚本。
我们将在这里利用popen
函数。
std::string exec(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
该函数接受命令作为参数,并以string
的形式返回输出。
注意:这将不捕获stderr!一个快速而简单的解决方法是将 stderr重定向到stdout,在命令末尾使用2>&1
。
这是popen
的文档。快乐编码:)
您必须使用popen
而不是system
来运行命令,然后循环遍历返回的文件指针。
ls -l
命令的一个简单示例#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *process;
char buff[1024];
process = popen("ls -l", "r");
if (process != NULL) {
while (!feof(process)) {
fgets(buff, sizeof(buff), process);
printf("%s", buff);
}
pclose(process);
}
return 0;
}
长方法——它让您完全控制子进程的stdin
、stdout
和stderr
,代价是相当大的复杂性——包括直接使用fork
和execve
。
-
在
fork
之前,设置您的通信端点-pipe
工作良好,或socketpair
。我假设您调用了如下内容:int childStdin[2], childStdout[2], childStderr[2]; pipe(childStdin); pipe(childStdout); pipe(childStderr);
-
fork
之后,execve
之前的子进程:dup2(childStdin[0], 0); // childStdin read end to fd 0 (stdin) dup2(childStdout[1], 1); // childStdout write end to fd 1 (stdout) dup2(childStderr[1], 2); // childStderr write end to fd 2 (stderr)
. .然后关闭
childStdin
、childStdout
和childStderr
的所有 -
fork
之后,父进程:close(childStdin[0]); // parent cannot read from stdin close(childStdout[1]); // parent cannot write to stdout/stderr close(childStderr[1]);
现在,父进程完全控制了子进程的std i/o,并且必须安全地复用childStdin[1]
、childStdout[0]
和childStderr[0]
,同时还监视SIGCLD
,并最终使用wait
系列调用来检查进程终止代码。pselect
特别适合在异步处理std i/o时处理SIGCLD
。当然也可以参见select
或poll
。
如果你想合并孩子的stdout
和stderr
,只dup2(childStdout[1], 2)
,把childStderr
完全去掉。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 函数何时会在c++中包含stack_Unwind_Resume调用