Piping (or command chaining) with QProcess
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");
qprocess get shell like behaviour
Is there any Qt like way to handle that and force Qt to use some default command line interpreter?
The simple answer is no, there isn't a Qt default command line interpreter
QString command = "grep \"false negatives\" test.txt | cut -f2";
This command doesn't work because QProcess takes the first token (grep) and uses that as the command, then passes each item, separated by a space to that command. In this case, the pipe command is not a valid argument for grep and neither is cut, nor -f2.
I commented that the answer to this question was possibly similar, as it demonstrates how you can successfully use the pipe command with QProcess; note that the arguments are surrounded by quotes.
As you don't want to call cmd or a *nix equivalent such as bash, you can handle this with two calls to QProcess; the first for the grep command and the 2nd for the cut, passing in the output from the first QProcess call.
The function QProcess::setStandardOutputProcess makes this easier, allowing you to create the pipe directly between the two QProcess objects.
Therefore you'd do something like this: -
QProcess proc1;
QProcess proc2;
proc1.setStandardOutputProcess(&process2);
QString cmd1("grep \"false negatives\" test.txt");
QString cmd2("cut -f2");
proc1.start(cmd1);
proc2.start(cmd2);
Ampersand(&) (very command execute) with QProcess
First, let's figure out what happens when you execute a single command, like pwd
. When you do it, the shell process forks (i.e. produces a child process), then the child process turns into pwd
process and acquires control over the terminal.
Next, if you execute pwd &
, all the same happens, but the child process (pwd
in our example) does not get control over the terminal. It runs as a background process, while the shell continues to work with the terminal. For example, you may run a GUI program (firefox &
), and the shell will be ready to run the next one immediately.
Finally, when you execute pwd & ls
, all the same as in the previous case happens, but the shell forks one more time and runs ls
in foreground. As you might guess, pwd & ls &
yields both processes being run in background, and you may execute as many commands as you want at once.
Now let's get back to Qt. QProcess
does not run any shell before running the command. Thus, when you run pwd & ls
via QProcess
, pwd
will be the only program executed, but it will get two command line arguments: &
and ls
. Both of them will be ignored.
So the equivalent of pwd & ls
will be two QProcess
objects, each running a single command.
Another solution is to run the shell explicitly to make the arguments being parsed:
QString cmd = "tcsh -c \"pwd & ls\"";
QProcess *process = new QProcess;
process->start(cmd);
process->waitForBytesWritten();
process->waitForFinished();
qDebug() << process->readAll();
How to execute complex linux commands in Qt?
The key methods that exist for this purpose established in QProcess
:
void QProcess::setProcessChannelMode(ProcessChannelMode mode)
and
void QProcess::setStandardOutputProcess(QProcess * destination)
Therefore, the following code snippet would be the equivalence of command1 | command2
without limiting yourself to one interpreter or another:
QProcess process1
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("echo myPass");
process2.start("sudo -S shutdown -r now");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
// Wait for it to start
if(!process1.waitForStarted())
return 0;
bool retval = false;
QByteArray buffer;
// To be fair: you only need to wait here for a bit with shutdown,
// but I will still leave the rest here for a generic solution
while ((retval = process2.waitForFinished()));
buffer.append(process2.readAll());
if (!retval) {
qDebug() << "Process 2 error:" << process2.errorString();
return 1;
}
You could drop the sudo -S
part because you could run this small program as root, as well as setting up the rights. You could even set setuid or setcap for the shutdown program.
What we usually do when building commercial Linux systems is to have a minimal application that can get setuid or setcap for the activity it is trying to do, and then we call that explicitly with system(3)
or QProcess
on Linux. Basically,
I would write that small application to avoid giving full root access to the whole application, so to restrict the access right against malicious use as follows:
sudo chmod u+s /path/to/my/application
QProcess: how to read output from pactl
The application you are trying to read from may be sending console output to stderr, in which case you have a few options:
just read from stderr outright: process.readAllStandardError()
set the read channel to read only from stderr: process.setReadChannel(QProcess::StandardError)
read from stderr and stdout with reckless abandon! : process.setProcessChannelMode(QProcess::MergedChannels)
Another possibility is that you are feeding incorrect arguments into your QProcess. It seems you are trying to pipe data above, the proper way to do this with QProcess is like this:
#include <QCoreApplication>
#include <QProcess>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QProcess pactl;
QProcess grep;
pactl.setStandardOutputProcess(&grep);
pactl.start("pactl list sinks short");
grep.start("grep 10_B7_F6_02_1B_4A");
pactl.waitForFinished();
grep.waitForFinished();
qDebug() << grep.readAll();
return EXIT_SUCCESS;
}
Related Topics
How to Load a Bmp on Glut to Use It as a Texture
What Does the Gcc Warning "Project Parameter Passing for X Changed in Gcc 7.1" Mean
Conversion from Int** to Const Int**
C++ Calculating More Precise Than Double or Long Double
Why Must Virtual Base Classes Be Constructed by the Most Derived Class
Making a Vector of Instances of Different Subclasses
Compare Equality of Char[] in C
Why Is My Double or Int Value Is Always 0 After Division
How to Get Size C++ Dynamic Array
Recursion in C++ Factorial Program
Best Bignum Library to Solve Project Euler Problems in C++
Variable or Field Declared Void
Does Reinterpret_Cast Lead to Undefined Behavior
Static Variable in the Class Declaration or Definition
When a Float Variable Goes Out of the Float Limits, What Happens