вместо.
ил: это, кажется, вопрос конкретной проблемы, но, надеюсь, он может быть отредактирован для всех связанных с
Мне нужно взаимодействовать с объектом QProcess.
Эта проблема:
Я не получаю вывод отQProcess
после звонкаQProcess:write(input)
Больше информации:
Проходя черезстраницы документа привел меня к созданию примера ниже:
У меня есть скрипт, запрашивающий ввод пользователя, и, наконец, отображение и соответствующее сообщение на основе ввода пользователя.
Тестирование:
После добавления функции «log» в мой скрипт для тестирования происходит следующее:
скрипт выполняетсяскрипт запрашивает ввод данных пользователем (подтверждается первым)qDebug() << p->readAll()
)скрипт принимает входные данные отQProcess
(подтверждено скриптом 'log output')После этого никакой вывод не получен. Следующие 2 оператора отладки оба запускаются (то есть ждут 30 секунд каждый)
if (!p->waitForReadyRead()) {
qDebug() << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
if (!p->waitForFinished()) {
qDebug() << "waitForFinished() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
С последующим:
QString s = QString(p->readAll() + p->readAllStandardOutput());
гдеs
пустая строка
Вопросs
должен содержат либо «успех» или «провал»
Телефонный код:
QString cmd = QString("sh -c \"/path/to/bashscript.sh\"");
QString input = QString("Name");
QString result = runCommand(cmd, input)
Код процесса:
//takes 2 parameters,
// cmd which is the code to be executed by the shell
// input which acts as the user input
QString runCommand(QString cmd, QString input){
QProcess *p = new QProcess(new QObject());
p->setProcessChannelMode(QProcess::MergedChannels); //no actual reason to do this
p->start(cmd);
if (p->waitForStarted()) {
if (!p->waitForReadyRead()) {
qDebug() << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
if (!p->waitForFinished()) {
//reads current stdout, this will show the input request from the bash script
//e.g. please enter your name:
qDebug() << p->readAll();
//here I write the input (the name) to the process, which is received by the script
p->write(ps.toLatin1());
//the script should then display a message i.e. ("success" o "failed")
if (!p->waitForReadyRead()) {
qDebug() << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
if (!p->waitForFinished()) {
qDebug() << "waitForFinished() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
}
QString s = QString(p->readAll() + p->readAllStandardOutput());
return s;
}
else{
qDebug() << "waitForStarted() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
p->waitForFinished();
p->kill();
return QString();
}
script.sh (-rwxrwxr-x
)
#!/bin/bash
#returns
# "success" on non empty $n value
# "failed: on empty $n value
#
echo "enter your name:"
read n
if [[ ! -z $n ]];
then
echo "success"
exit 0;
else
echo "failed"
exit 1;
fi
ОБНОВИТЬ
@KevinKrammer Я изменил команду запуска, как вы сказали, также используя QStringList с аргументами.
По-прежнему не получает вывод, на самом делеwaitForReadyRead()
а такжеwaitForFinished()
returns false
мгновенно.
Вызывается с:
QString r = runCommand(QString("text"));
Код процесса:
QString runCommand(QString input){
QProcess *p = new QProcess(new QObject());
p->setProcessChannelMode(QProcess::MergedChannels);
//script is the same script refered to earlier, and the `cd /home/dev` IS required
p->start("sh", QStringList() << "-c" << "cd /home/dev" << "./script");
;
if (p->waitForStarted()) {
if (!p->waitForReadyRead(5000)) {
qDebug() << "waitForReadyRead() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
qDebug() << p->readAll();
p->write(input.toLatin1());
if(!p->waitForFinished(5000)){
qDebug() << "waitForFinished() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
QString s = QString(p->readAll() + p->readAllStandardOutput());
return s;
}
else{
qDebug() << "waitForStarted() [false] : CODE: " << QVariant(p->error()).toString() << " | ERROR STRING: " << p->errorString();
}
p->waitForFinished();
p->kill();
return QString();
}
Терминальный вывод процесса:
started
readChannelFinished
exit code = "0"
waitForReadyRead() [false] : CODE: "5" | ERROR STRING: "Unknown error"
""
waitForFinished() [false] : CODE: "5" | ERROR STRING: "Unknown error"
Press <RETURN> to close this window...
Мысли об этом?
ОБНОВЛЕНИЕ 2
@Tarod Спасибо, что нашли время, чтобы найти решение.
Это работает, однако не полностью ожидается.
Я точно скопировал ваш код.
Сделано несколько изменений вmReadyReadStandardOutput()
Смотрите дополнительную информацию ниже.
Эта проблема:
После запуска приложения (и скрипта) я получаю результат -> УДИВИТЕЛЬНЫЙ
Каждый раз это неверный результат, то есть «провал». -> НЕ УДИВИТЕЛЬНЫЙ
Терминальный выход:
void MyProcess::myReadyRead()
void MyProcess::myReadyReadStandardOutput()
"enter your name:\n"
""
void MyProcess::myReadyRead()
void MyProcess::myReadyReadStandardOutput()
"failed\n"
Press <RETURN> to close this window...
содержание скрипта:
#!/bin/bash
echo "enter your name:"
read n
echo $n > "/tmp/log_test.txt"
if [[ ! -z "$n" ]];
then
echo "success"
exit 0;
else
echo "failed"
exit 1;
fi
/tmp/log_test.txt
выход
myname
запустить это вручную из консоли:
dev@dev-W55xEU:~$ ls -la script
-rwxrwxr-x 1 dev dev 155 Jan 25 14:53 script*
dev@dev-W55xEU:~$ ./script
enter your name:
TEST_NAME
success
dev@dev-W55xEU:~$ cat /tmp/log_test.txt
TEST_NAME
Полный код:
#include <QCoreApplication>
#include <QProcess>
#include <QDebug>
class MyProcess : public QProcess
{
Q_OBJECT
public:
MyProcess(QObject *parent = 0);
~MyProcess() {}
public slots:
void myReadyRead();
void myReadyReadStandardOutput();
};
MyProcess::MyProcess(QObject *parent)
{
connect(this,SIGNAL(readyRead()),
this,SLOT(myReadyRead()));
connect(this,SIGNAL(readyReadStandardOutput()),
this,SLOT(myReadyReadStandardOutput()));
}
void MyProcess::myReadyRead() {
qDebug() << Q_FUNC_INFO;
}
void MyProcess::myReadyReadStandardOutput() {
qDebug() << Q_FUNC_INFO;
// Note we need to add \n (it's like pressing enter key)
QString s = this->readAllStandardOutput();
qDebug() << s;
if (s.contains("enter your name")) {
this->write(QString("myname" + QString("\n")).toLatin1());
qDebug() << this->readAllStandardOutput();
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyProcess *myProcess = new MyProcess();
QString program = "/home/dev/script";
myProcess->start("/bin/sh", QStringList() << program);
a.exec();
}
#include "main.moc"
вопрос сценария? Вопрос QProcess?