确定 QProcess 是否已完成执行或正在等待用户输入(或响应)
Determine if QProcess has finished executing or is awaiting user input (or response)
我有 2 bash 个脚本
- 一个不需要用户输入的脚本,它显示信息
- 另一个需要一些用户输入,也显示一些信息
问题:
创建 QProcess
时,我无法区分 QProcess
是已完成还是挂起以等待用户输入。
我希望有一些功能,例如QProcess::atEnd
如果脚本完成,returns 为真,但即使 QProcess
挂起以等待用户输入(来自脚本),它 returns 也为真
更多信息:
需要用户输入的脚本:name-please.sh
不需要输入的脚本:hello.sh
姓名-please.sh
#!/bin/bash
echo "I am Mr Robot"
echo "what is your name:"
read n
if [[ ! -z "$n" ]];
then
echo "please to meet you"
exit 0;
else
echo "ok, bye..."
exit 1;
fi
hello.sh
#!/bin/bash
echo "I am Mr Robot"
使用 mReadyReadStandardOutput()
,我阅读了脚本输出。问题存在于我需要读取输出、确定输出是否包含请求用户信息的行(脚本中的行)并对此做出响应这一事实。
查看带有指向行的指针的代码
代码:
#include <QCoreApplication>
#include <QLoggingCategory>
#include <QTextStream>
#include <QProcess>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QObject>
#include <QEventLoop>
class m_Proc : public QProcess
{
Q_OBJECT
public:
int exitCode = -1;
QString _out, _input;
m_Proc(QString input = QString(), QObject *parent = 0);
~m_Proc() {}
public slots:
void myReadyReadStandardOutput();
void myFinished(int i);
};
m_Proc::m_Proc(QString input, QObject *parent)
{
connect(this,SIGNAL(readyReadStandardOutput()),
this,SLOT(myReadyReadStandardOutput()));
connect(this, SIGNAL(finished(int)),
this, SLOT(myFinished(int)));
}
void m_Proc::myReadyReadStandardOutput() {
// Note we need to add \n (it's like pressing enter key)
_out = this->readAllStandardOutput();
if (!_input.isEmpty()) {
/*
* check if line matches that of the script,
* where the user is required to enter their name
*/
if (_out.contains("what is your name")) { <<< ---- LINE WITH ISSUE
this->write(QString(_input + QString("\n")).toLatin1());
_out = this->readAllStandardOutput();
}
}
else
qDebug() << "Input Emptry (should not be reached!) !";
}
void m_Proc::myFinished(int i){
exitCode = i;
qDebug() << "exit code = " << QString::number(exitCode);
qDebug() << _out;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
m_Proc *myProcess1 = new m_Proc(QString("text"));
// QString program = "/home/dev/script";
myProcess1->start("/home/dev/script", QStringList());// << "one" << "two");
// myProcess1->start("/bin/sh", QStringList() << "-c" << "ls" << "-la");
a.exec();
}
#include "main.moc"
有什么绕过这个问题的建议吗?
三件事。
根据 QProcess::atEnd()
的文档,仅当进程不是 运行 (QProcess::NotRunning
) 时,此 return 才为真。那么...您 确定 当您调用 atEnd()
时,流程并未真正完成吗?我在您发布的代码中没有看到它,所以我无法判断。
每次有新数据可用时,您的 myReadyReadStandardOutput()
信号都会覆盖 m_Proc::_out
成员变量。根据系统(以及 Qt)缓冲标准输出的写入方式,您可能会将部分行读入 _out
。因此 _out.contains()
调用可能 return 错误,因为你在行中有类似 at is your
的内容,而不是完整的 what is your name:
.
您将成员字符串_input
写入进程的标准输入,然后立即尝试从标准输出再次读取。这将 很可能不会 return 您在 _out
中还没有 的任何数据。当控制 return 到主事件循环时,Qt 只对底层设备进行实际的 I/O 操作。来自 QIODevice
的文档:
Certain subclasses of QIODevice, such as QTcpSocket and QProcess, are asynchronous. This means that I/O functions such as write() or read() always return immediately, while communication with the device itself may happen when control goes back to the event loop.
我对解决您的问题的建议是修改 myReadyReadStandardOutput
信号。对于异步设备(例如套接字和 sub-processes),数据可能以 arbitrary-sized 块的形式到达。这是我上面做的2点。通常处理这个问题的方法是在信号的顶部放置如下内容:
if (!canReadLine())
return;
因此,如果整行数据不可用,则退出信号并 return 进入主事件循环。如果 return 为真,您可以执行以下操作:
_out = readLine();
/* Process an entire line, e.g., check if it matches the request for name */
因此信号被设计为仅对整行数据进行操作。这对于 line-oriented 的终端或网络协议很有用。在这种情况下,您可以调用 QString::contains()
方法来检查这是否是请求名称的行,如果是,则写入它。但是您必须然后 return 到事件循环 才能写入数据,因此您将在下一行处理下一行 (please to meet you
)调用其中有完整行的信号。
我有 2 bash 个脚本
- 一个不需要用户输入的脚本,它显示信息
- 另一个需要一些用户输入,也显示一些信息
问题:
创建 QProcess
时,我无法区分 QProcess
是已完成还是挂起以等待用户输入。
我希望有一些功能,例如QProcess::atEnd
如果脚本完成,returns 为真,但即使 QProcess
挂起以等待用户输入(来自脚本),它 returns 也为真
更多信息:
需要用户输入的脚本:
name-please.sh
不需要输入的脚本:
hello.sh
姓名-please.sh
#!/bin/bash
echo "I am Mr Robot"
echo "what is your name:"
read n
if [[ ! -z "$n" ]];
then
echo "please to meet you"
exit 0;
else
echo "ok, bye..."
exit 1;
fi
hello.sh
#!/bin/bash
echo "I am Mr Robot"
使用 mReadyReadStandardOutput()
,我阅读了脚本输出。问题存在于我需要读取输出、确定输出是否包含请求用户信息的行(脚本中的行)并对此做出响应这一事实。
查看带有指向行的指针的代码
代码:
#include <QCoreApplication>
#include <QLoggingCategory>
#include <QTextStream>
#include <QProcess>
#include <QString>
#include <QVariant>
#include <QDebug>
#include <QObject>
#include <QEventLoop>
class m_Proc : public QProcess
{
Q_OBJECT
public:
int exitCode = -1;
QString _out, _input;
m_Proc(QString input = QString(), QObject *parent = 0);
~m_Proc() {}
public slots:
void myReadyReadStandardOutput();
void myFinished(int i);
};
m_Proc::m_Proc(QString input, QObject *parent)
{
connect(this,SIGNAL(readyReadStandardOutput()),
this,SLOT(myReadyReadStandardOutput()));
connect(this, SIGNAL(finished(int)),
this, SLOT(myFinished(int)));
}
void m_Proc::myReadyReadStandardOutput() {
// Note we need to add \n (it's like pressing enter key)
_out = this->readAllStandardOutput();
if (!_input.isEmpty()) {
/*
* check if line matches that of the script,
* where the user is required to enter their name
*/
if (_out.contains("what is your name")) { <<< ---- LINE WITH ISSUE
this->write(QString(_input + QString("\n")).toLatin1());
_out = this->readAllStandardOutput();
}
}
else
qDebug() << "Input Emptry (should not be reached!) !";
}
void m_Proc::myFinished(int i){
exitCode = i;
qDebug() << "exit code = " << QString::number(exitCode);
qDebug() << _out;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
m_Proc *myProcess1 = new m_Proc(QString("text"));
// QString program = "/home/dev/script";
myProcess1->start("/home/dev/script", QStringList());// << "one" << "two");
// myProcess1->start("/bin/sh", QStringList() << "-c" << "ls" << "-la");
a.exec();
}
#include "main.moc"
有什么绕过这个问题的建议吗?
三件事。
根据
QProcess::atEnd()
的文档,仅当进程不是 运行 (QProcess::NotRunning
) 时,此 return 才为真。那么...您 确定 当您调用atEnd()
时,流程并未真正完成吗?我在您发布的代码中没有看到它,所以我无法判断。每次有新数据可用时,您的
myReadyReadStandardOutput()
信号都会覆盖m_Proc::_out
成员变量。根据系统(以及 Qt)缓冲标准输出的写入方式,您可能会将部分行读入_out
。因此_out.contains()
调用可能 return 错误,因为你在行中有类似at is your
的内容,而不是完整的what is your name:
.您将成员字符串
_input
写入进程的标准输入,然后立即尝试从标准输出再次读取。这将 很可能不会 return 您在_out
中还没有 的任何数据。当控制 return 到主事件循环时,Qt 只对底层设备进行实际的 I/O 操作。来自QIODevice
的文档:
Certain subclasses of QIODevice, such as QTcpSocket and QProcess, are asynchronous. This means that I/O functions such as write() or read() always return immediately, while communication with the device itself may happen when control goes back to the event loop.
我对解决您的问题的建议是修改 myReadyReadStandardOutput
信号。对于异步设备(例如套接字和 sub-processes),数据可能以 arbitrary-sized 块的形式到达。这是我上面做的2点。通常处理这个问题的方法是在信号的顶部放置如下内容:
if (!canReadLine())
return;
因此,如果整行数据不可用,则退出信号并 return 进入主事件循环。如果 return 为真,您可以执行以下操作:
_out = readLine();
/* Process an entire line, e.g., check if it matches the request for name */
因此信号被设计为仅对整行数据进行操作。这对于 line-oriented 的终端或网络协议很有用。在这种情况下,您可以调用 QString::contains()
方法来检查这是否是请求名称的行,如果是,则写入它。但是您必须然后 return 到事件循环 才能写入数据,因此您将在下一行处理下一行 (please to meet you
)调用其中有完整行的信号。