进程结束时如何保持 QProcess 执行的命令?

Posted

技术标签:

【中文标题】进程结束时如何保持 QProcess 执行的命令?【英文标题】:How do I keep a command executed by QProcess when the process ends? 【发布时间】:2018-08-30 00:43:41 【问题描述】:

我正在尝试找到一种方法来在 Linux 系统中终止 GUI 程序后保持QProcess 执行的命令。现在,当进程结束时,所有执行的命令都消失了。 QProcess 终止后有没有办法保留它?

// code which executes command in linux
QProcess *mproc = new Qprocess(this);
QStringList args;
mproc->setWorkingDirectory("/home/test");
args << "-c" << "source tool_def1.env; source tool_def2.env; myProg";
mproc->start("/bin/csh", args);

tool_def1.envtool_def2.env 文件包含一些用于执行myProg 的环境变量,例如set path = (~~~~)

在 GUI 程序中,这段代码做得很好。而且,我想在 GUI 程序终止后运行 GUI 程序的终端中执行myProg 程序。

但是,如果GUI程序被终止,我无法运行myProg,因为tool_def1.envtool_def2.env文件的环境变量消失了。

是否可以保留环境变量?或者,是否可以在其他进程中执行myProg程序,环境变量为mproc进程如下?

QProcess *mproc2 = new QProcess(this);
mproc2->setWorkingDirectory("/home/test2");
mproc2->start("myProg");

【问题讨论】:

doc.qt.io/qt-5/qprocess.html#startDetached 谢谢你,scopchanov。我尝试使用 startDetached,但效果不佳。在我的 GUI 程序中,它运行良好。但是,当 GUI 程序运行或终止时,在终端中还找不到“myProg”。此外,“mproc2”进程不起作用。我只在我的代码中将 'start' 交换为 'startDetached'。对吗?? 要检查的几个问题:您确定 startDetached 的返回是真的吗?您是否检查了返回的 PID?你确定它一直在运行吗? (也许写一些你可以检查的日志文件) 我检查了 startDetached 的返回是否为真,并且“myProg”运行良好。但是,在我关闭 GUI 程序和“myProg”后,当我在终端的 shell 提示符下再次执行 myProg 时,myProg 不起作用并显示“找不到命令”消息。 【参考方案1】:

你使用的QProcess::startDetached的重载是一个静态方法,所以它不会考虑特定实例的属性,即mproc-&gt;setWorkingDirectory("/home/test")不为静态方法设置工作目录,只为@987654326设置工作目录@。当你启动进程时,由于没有为静态调用设置工作目录,因此无法找到程序并失败。

正如您在文档中看到的那样,静态 startDetached 也承认工作目录作为参数,因此您可以将代码更改为:

QStringList args;
args << "-c" << "source tool_def1.env; source tool_def2.env; myProg";
QProcess::startDetached("/bin/csh", args, "/home/test");

另一种方式是使用非静态版本,需要单独指定程序:

QProcess mproc(this);

QStringList args;
args << "-c" << "source tool_def1.env; source tool_def2.env; myProg";
mproc.setArguments(args);

mproc.setWorkingDirectory("/home/test");
mproc.setProgram("/bin/csh");

qint64 pid; // to store the process ID (will become invalid if the child process exits)
mproc.startDeatached(&pid);

关于第二个问题,请看QProcess::setProcessEnvironment。只是您必须使用非静态方式来设置流程的环境。可以使用QProcess::systemEnvironment获取当前进程的环境变量。

mproc.setProcessEnvironment(QProcess::systemEnvironment());

来自 cmets 的更新:如果您希望在 GUI 应用程序运行时始终使用活动的环境变量(它是某种配置器吗?)您可以将它们保存到文件(例如 JSON)中,然后加载并从第二个过程手动设置它们。

要提取它们,您可以执行以下操作:

const auto env_vars = QProcess::systemEnvironment().toStringList();

现在env_vars 将是格式为NAME_OF_ENVAR=VALUE_OF_ENVAR 的字符串列表。您可以将此类列表保存到文件中(您需要在每行的开头添加一个 export 才能与 source 一起使用)。


我已经在 Windows(VS 15.8.2 和 Qt 5.10.0)中测试了静态版本,它按预期工作。使用的代码:

#include <qprocess.h>

int main(int argc, char* argv[])

  QProcess::startDetached("cmd", QStringList() << "/c" << "test.exe", "../test/");

  return 0;

其中test.exe的代码基本上是一个永无止境的过程。


注意:一个有趣的事实,作为使用 VS 的开发人员的注意事项。对于相同的程序和构建,如果从命令行执行,它可以正常工作:应用程序结束,第二个进程继续在后台运行,但如果从 VS IDE 执行,则 控制台窗口 保持活着,如果我关闭它,第二个进程也会被杀死。调试时,调试器结束,但仍显示控制台。我想这是因为 VS 在从 IDE 启动时以某种方式跟踪所有创建的进程。

【讨论】:

谢谢。但是我的问题还没有解决。我想在 GUI 程序关闭后再次执行“myProg”程序,而不是继续运行在运行 GUI 程序期间执行的“myProg”程序。在 GUI 程序和“myProg”都终止后,我希望在终端窗口的 shell 提示符下输入“myProg”(执行命令)时再次执行“myProg”。所以我想在 GUI 程序终止后保留环境变量。有可能吗? 我不明白:你想执行 myProg 但在 GUI 结束时关闭它,然后从 shell 手动恢复它,但使用 GUI 执行期间存在的环境变量?在这种情况下,只需将它们保存到文件(JSON、XML、INI...),并在从 shell 执行时重新加载它们。例如,您可以在 GUI 中添加一个命令行参数来指示必须存储 EV,如果省略(从 CLI 中)则从文件中加载它们。这就是你想要的吗? 是的!但是,我对 JSON、XML、INI、CLI 不太了解……是否可以应用 env。 GUI程序中终端的变量??? 使用任何你想写/读的文件格式,它们只是示例(尽管我鼓励你学习它们,因为它们非常有用)... CLI 代表:命令行界面(shell ) 用于应用环境变量的文件已经存在。 (tool_def1.env / tool_def2.env) 而且,我还可以通过在终端中输入“source”来运行“myProg”。但是,一旦应用于 GUI 程序,我想重用相同的变量,而不是再次采购它们。有可能吗?

以上是关于进程结束时如何保持 QProcess 执行的命令?的主要内容,如果未能解决你的问题,请参考以下文章

Qt QProcess startDetached 无法结束进程(bash 会话)

如何在 Windows 上通过 QProcess 启动提升的子进程?

Qt笔记-QProcess切换用户执行进程(Linux)

QT使用QProcess类,判断某个进程是否存在

QT使用QProcess类,判断某个进程是否存在

Qt 调用进程 QProcess的使用详解