I'm using Qt and bash over it, need to execute something like:
bash: cat file | grep string
in Qt:
QString cmd = "cat file | grep string";
QProcess *process = new QProcess;
process->start(cmd);
process->waitForBytesWritten();
process->waitForFinished();
qDebug() << process->readAll();
The problem is in pipe ("|"), and process returs nothing. If there is no ("|"), like
"cat file"
everything is ok.
I tried smth. like
"cat file \\| grep string",
"cat file \| grep string"
but result is the same. If I copy the command and run it in bash everything is ok.
QString::toAscii().data()
and other transforms also have bad result.
The problem is you cannot run a system command with QProcess, but only a single process. So the workaround will be to pass your command as an argument to bash:
process.start("bash", QStringList() << "-c" << "cat file | grep string");
The quick and dirty hack would be this:
QString cmd = "/bin/sh -c \"cat file | grep string\"";
You could also avoid the escaping in there with C++11's R"", but the point is that do not use bash in there because that will make it only work with bash. It will not work on embedded with busybox without bash, just ash, or any other common desktop shell.
/bin/sh is usually a symlink to the shell interpreter used, so that will eventually work.
BUT!
I think you are thinking a bit too low-level when using a high-level C++/OOP framework such as Qt. I would not recommend to invoke the commands in the low-level way when you run it from bash. There is some dedicated high-level convenience API for this use case.
Based on the official documentation, QProcess is supposed to work for pipe'd commands:
void QProcess::setStandardOutputProcess(QProcess * destination)
Pipes the standard output stream of this process to the destination process' standard input.
In other words, the command1 | command2 shell command command can be achieved in the following way:
QProcess process1;
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("cat file");
process2.start("grep string");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
// Wait for it to start
if(!process1.waitForStarted())
return 0;
bool retval = false;
QByteArray buffer;
while ((retval = process2.waitForFinished()));
buffer.append(process2.readAll());
if (!retval) {
qDebug() << "Process 2 error:" << process2.errorString();
return 1;
}
qDebug() << "Buffer data" << buffer;
This is not the main point, but a useful suggestion: do not use QString::toAscii(). That API has been deprecated in Qt 5.
The problem is that when you call process->start(cmd), the commands following the the call to cat are all interpreted as arguments to cat, so the pipe is not doing what you're expecting. If you start with a call to bash with a parameter of a string, you should get what you want: -
QString cmd = "bash -c \"cat file | grep string\"";
Alternatively, you could just call "cat file" and do the search on the returned QString when you read the output from the QProcess
how about this :
QString program = "program";
QStringList arguments;
download = new QProcess(this);
download->start(program, arguments);
If Google brought you here and you are using PyQt5 or PySide2
process1 = QProcess()
process2 = QProcess()
process1.setStandardOutputProcess(process2)
process1.start(cat, [file])
process2.start(grep, [string])
I am trying to execute following command and trying to get the output however I am getting output as null.
QProcess process;
process.start("cmd /c \"ipconfig\"");
process.waitForFinished(-1);
QByteArray out = process.readAll();
QString testStr = QString::fromUtf8(out);
Can someone please tell me where am I doing wrong?
process.start("C:\\Windows\\System32\\cmd.exe /c \"ipconfig\"");
I want to open a project of QGIS from a QProcess object.
If I am under console I must type
qgis --project /path/of/my/qgis/project/nameofproject.qgs
Then, I do the next:
QString app="qgis";
QStringList arguments;
arguments.append ("--project /path/of/my/qgis/project/nameofproject.qgs");
And then I call it in this way:
proceso->start(app,arguments);
But I have this error in the call:
Cannot find /home/david/Programacion/Qt/SQL/Sql2/build-prueba2-Desktop_Qt_5_3_GCC_64bit-Debug/--project /home/david/GIS/CRCC.qgs
where:
/home/david/Programacion/Qt/SQL/Sql2/build-prueba2-Desktop_Qt_5_3_GCC_64bit-Debug/ is the path of my Qt application and
--project /home/david/GIS/CRCC.qgs is the path I set in the arguments QStringList
I don know how must I set the QProcess object for avoid the path of my app.
Thank you
I would try this in the following ways. With a single command:
const QString command( "qgis --project /path/of/my/qgis/project/nameofproject.qgs" );
QProcess process;
process.start( command );
Or with arguments:
const QString program( "qgis" );
QStringList arguments;
arguments << "--project";
arguments << "/path/of/my/qgis/project/nameofproject.qgs";
QProcess process;
process.start( program, arguments );
In my Qt app i run a process under a push-button click.The process run gnome-terminal.My problem is when i kill qt process that run but push-button click from another button by pid,its shows error."kill: sending signal to 19771 failed: No such process" but still terminal running.And if i kill my app,but still terminal running.
QProcess *p = new QProcess(this);
if (p)
{
p->setEnvironment( QProcess::systemEnvironment() );
p->setProcessChannelMode( QProcess::MergedChannels );
QString program = "gnome-terminal";
QStringList arguments;
arguments << "-x" << "bash" << "--rcfile" << "./auto.sh";
p->start(program, arguments);
pid= p->pid();
}
Button2 cod is:
QProcess::startDetached("kill -9 "+QString(pid));
how can kill process and also terminal by click another push-button?
I want to launch a shell script with Qt.
QProcess process;
process.start(commandLine, QStringList() << confFile);
process.waitForFinished();
if(process.exitCode()!=0)
{
qDebug () << " Error " << process.exitCode() << process.readAllStrandardError();
}
else
{
qDebug () << " Ok " << process.readAllStrandardOutput() << process.readAllStrandardError();
}
The result is :
Ok : Result.... " "" QProcess : Destroyed while process is still
running.
This message does not appear every time.
What is the problem?
process.waitForFinished(); is hitting the default 30 seconds timeout. Use process.waitForFinished(-1); instead. This will make sure you wait for however long it takes for the process to finish, without any timeout.
Note you create QProcess into the local scope. This means that the object will be deleted when you exit the scope. In the destructor QProcess process terminates. The message "Destroyed" while "the process is still running" when the process terminates in the destructor.
For solving this problem, you should call QProcess destructor when process is already terminated.
If will be QProcess::waitForFinished(-1) into your example, it will occur, but this will block you application.