【问题标题】:Redirecting output from gnome-terminal using QProcess in C++在 C++ 中使用 QProcess 重定向来自 gnome-terminal 的输出
【发布时间】:2012-11-26 00:34:47
【问题描述】:

我正在尝试为将生成终端的 gui 生成子进程。我希望此终端(stdout 和 stderr)生成的数据显示在出现的窗口以及设置的日志文件中。当我将命令直接输入到 shell 中时,它会按预期工作,但是当作为启动命令提供给 QProcess 时,它实际上并没有向文件写入任何内容。

例如:如果用户没有安装二进制文件,它应该向 bin.log 写入命令未找到。我已将生成的 QProcess 的环境设置为与正在运行的父进程相同(以便它可以找到 bash 和其他任何内容),并在调用 QProcess.start() 方法之前设置了工作目录。我写了一个测试用例如下:

gnome-terminal --title 'Sub-Terminal' -e 'bash -c "foo [args to foo] |& tee foo.log"'

在 Qt 中,我执行以下操作:

QProcess *child = new QProcess(this);
QString   cmd   = "gnome-terminal --title 'Sub-Terminal' -e 'bash -c \"foo [args to foo] |& tee foo.log\"'";
child->setProcessEnvironment(<process environment I have created before>);
child->setWorkingDirectory(<current working dir>);
child->start(cmd);
...

它生成终端但不向 foo.log 写入任何数据。我还尝试了以下方法:

QProcess *child = new QProcess(this);
QString   prog  = "gnome-terminal"
QStringList args;
args << "-x" << "bash" << "foo" << "[foo's arguments]" << "|&" << "tee" << "foo.log";
// set the process env and working dir
child->start(prog, args);

有人对如何解决这个问题有任何建议吗? 我尝试使用 QProcess.setStandardErrorFile(foo.log) 和 QProcess.setStandardOutputFile(foo.log) 重定向 stdout 和 stderr,但似乎这会从 gnome 终端本身重定向标准输出(这不是什么)。

【问题讨论】:

    标签: c++ linux qt qprocess gnome-terminal


    【解决方案1】:

    您必须在"-e" 之后将要在终端中执行的整个命令作为单个参数提供给QProcess,并将在bash 中执行的命令作为单个参数提供给bash:

    args << "-e" << "bash -c 'foo [args to foo] |& tee foo.log'";
    

    这基本上执行

    bash -c 'foo [args to foo] |& tee foo.log'
    

    在终端中,它自己执行

    foo [args to foo] |& tee foo.log
    

    在 bash 中。

    您猜对了,从 gnome-terminal 进程读取输出不起作用。

    【讨论】:

    • 遗憾的是这似乎不起作用。将 foo 替换为 ls(无参数)时,出现以下错误:未能执行子进程“bash -c 'ls |& tee tester.out'”(没有这样的文件或目录)
    • 用 '-e' 参数替换 gnome-terminal 的 '-x' 参数会导致一切正常!我不完全确定是什么导致了这种行为差异。 -x 表示它执行命令行的其余部分,而 -e 表示它在 shell 中将参数作为字符串执行。看到这两个参数都是该行的其余部分,我不确定有什么区别。
    • @user1886389 这意味着例如:gnome-terminal -x ls foo 执行 ls foo,而 gnome-terminal -e ls foo 执行 ls 并且它不知道如何处理另一个参数 foo(它们是两个参数!)但gnome-terminal -e "ls foo" 将执行ls foo(因为它是一个单个参数)。谢谢你的提示。我习惯写-e,所以我只是没有注意到你在另一个代码sn-p中写了-x,它的行为与我们现在知道的不同;)如果你对这个答案感到满意,请点赞和/或接受它。顺便说一句:欢迎来到 Stack Overflow! ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多