Use QProcess to only zcat as many lines as needed? - c++

In Linux if I run this command
zcat bigFile | head
Then zcat will not decompress all of bigFile, only as much as it needs to in order to supply head with the data it needs.
But what about this
QProcess *process = new QProcess(this);
process->start("zcat bigFile");
process->readLine();
QTimer::singleShot(10000, process, SLOT(terminate()));
Will the zcat command that is run in process only decompress whatever is needed for readLine()? Or will it continuously zcat bigFile for 10 seconds?
Is it possible to use a QProcess similarly to the Linux pipe |, and thus only zcat as many lines as have been requested?

Will the zcat command that is run in process only decompress whatever
is needed for readLine()?
No
Or will it continuously zcat bigFile for 10 seconds?
Yes
To verify this, I wrote the following code
QProcess *process = new QProcess(this);
process->start("yes");
connect(process, SIGNAL(finished(int)), this, SLOT(_end()));
connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(_end()));
QByteArray byteArray = process->readLine(5);
QString line = QString(byteArray);
process->closeReadChannel(QProcess::StandardOutput);
QTimer::singleShot(5000, process, SLOT(terminate()));
This basically starts the yes command which continuously outputs this
y
y
y
y
... (and so on)
And then reads only one line from the output of yes, and then terminates the process 5 seconds later.
I ran this command while watching top, and the result is 5 seconds of yes taking 100% CPU, after which it quits. This clearly shows that yes does not merely print out one line and then halt or quit.
Even closing the stdout read channel (which ignores the rest of the output of yes) still doesn't pause the yes execution.
You could try pausing the QProcess periodically until you have enough time to process the buffer, but that could get messy.

When you call start() on QProcess, it executes the zcat program, as it does in a terminal. This is a separate process from your Qt program, so it's free to run independently from your Qt application, or in the case of the code you've provided, it will run until it is terminated 10 seconds later.
Whether or not you choose for your application to read the output from zcat is up to you, but it will still continue to run.
Also note that calling process->readline() straight afterwards is probably not the best way of handling the process as your program may try to read the output stream before any data is ready. Instead, you should either call waitForReadyRead() before readline(), or connect a slot to readyRead() signal of QProcess and call readline from that slot.
---- EDITED -----
Based on the change to the question: -
I think you're missing the point of the pipe command. As I understand it, all of the file will be decompressed by zcat, but its output is redirected to the head command. The head command only displays the first number of lines of a file, which is why you only see the first part.
This is like having a file test.txt and calling the command: -
cat test.txt | head
The whole file exists, but head will only display the first number of lines.

Related

wait until shell command is executed

I have a script where I launch a shell command. The problem is that the script doesn't wait until the command is finished and continues right away.
I have tried WAIT but it doesn't work as the shell command turns the source off and on (ignition off/on) and I get the error that WAIT cannot be executed because power is off.
Is there any command I can use for program to wait until the command is executed?
My script looks like this:
OS.COMMAND echo OUTP OFF > COM1
OS.COMMAND echo OUTP ON > COM1
System.up
If I would want to execute a shell command without redirecting I would use OS.Area instead of OS.Command, because OS.Area is blocking and will wait until the shell command has finished. However OS.Area does not support redirecting I think.
If I would want to execute a shell command and redirect the output to a file I would first delete the file and then wait until it gets accessible. Like this:
IF OS.FILE.EXIST("myfile.txt")
RM "myfile.txt"
OS.Command ECHO "Hello World" > "myfile.txt"
WAIT OS.FILE.readable("myfile.txt")
However it looks like you want to write via a shell command to a COM port on Windows. But I don't think it is possible to wait in TRACE32 until this write to the COM port has been done when using OS.Command...
So I suggest to do this task with the TERM commands instead:
TERM.METHOD #1 COM COM1 115200. 8 NONE 1STOP NONE
TERM.view #1
TERM.Out #1 "OUTP OFF" 0x0A
TERM.Out #1 "OUTP ON" 0x0A
Of course you have to set the correct baud rate, bits, parity and stop bits. The 0x0A after each TERM.Out is simply the line-feed character.
Does you terminal show any output as a reaction to OUTP ON? If yes you can also wait for this output with e.g. SCREEN.WAIT TERM.LINE(#1,-1)=="OUTP is now ON" 5.s
Otherwise I assume that a simple WAIT 50.ms before SYStem.Up will probably do the trick too.

Control ubuntu terminal from Qt C++

I want to write a routine that will automatically change my Machine learning parameters and execute the (Machine learning) code multiple times and save its result into a text file.
The Machine learning code is run from the Ubuntu terminal and its result also are written to the Ubuntu terminal.
I need a way to read data and write data to the Ubuntu terminal from the C++ code.
What I have found so far is the QProcess:
QProcess process;
process.start("gnome-terminal"); //THE TERMINAL IS OPENED INDEED
char w[] = "write";
process.write(w,sizeof(w));
process.waitForFinished();
But nothing is written or read from it
What does working is:
QProcess process1;
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("echo 0534230313");
process2.start("sudo -S poweroff");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
And also this works:
int result = system("echo 0534230313 | sudo -S poweroff"); ///COMMANDS TO TERMINAL
int result2 = system("gnome-terminal"); ///OPEN TERMINAL
But the problem is that I wont be able to read the output result (My Machine learning program can open and write to the terminal by itself)
Use the finished signal to read the process output results
connect( poProcess, static_cast<void (QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
[=](int,QProcess::ExitStatus)
{
QByteArray oProcessOutput=
poProcess->readAllStandardOutput();
// Parse the process output.
//
// Mark process for deletion.
emit poProcess->deleteLater();
});

Qt QProcess how to write to standard in?

I am starting a QProcess to open cmd.exe.
I want to write to std in to send commands to cmd.exe, and I want to recieve it's output.
QProcess mProcess = new QProcess(this);
mProcess->setReadChannelMode(QProcess::SeparateChannels);
mProcess->start("cmd");
QApplication::processEvents();
QString s(mProcess->readAllStandardOutput());
writeToConsole(s);
This all works just fine. The process starts, I get output. However, I can't now write to the process anymore. I have looked over QProcess documentation and I don't see any way to write to standard in. I've tried mProcess->write(data); but that didn't do anything.
How do I write to standard in to the running process?
You have to use write function only to write in to the standard in.
But the important thing is you have to close the write channel using void QProcess::closeWriteChannel().
Look into below documentation.
http://doc.qt.io/qt-5/qprocess.html#closeWriteChannel
You should wait for operations to finish before moving on to the next action.
QProcess mProcess = new QProcess(this);
mProcess->setReadChannelMode(QProcess::SeparateChannels);
//Start the process
mProcess->start("cmd");
QApplication::processEvents();
mProcess->waitForStarted();
// Read the output
mProcess->waitForReadyRead();
QString output(mProcess->readAllStandardOutput());
mProcess->closeReadChannel();
// Write the data
mProcess->write(output);
mProcess->waitForBytesWritten();
mProcess->closeWriteChannel();
// Wait for finished
mProcess->waitForFinished();
It seems strange to send the output directly back into the program being executed. Alternatively you could connect the void QIODevice::readyRead() signal to a slot where the output can be handled elsewhere.
The mistake I was making here was not putting \n on the end of the multiple commands.
''''
// 1st command
mProcess->write(output1 + "\n");
mProcess->waitForBytesWritten();
// 2nd command
mProcess->write(output1 + "\n");
mProcess->waitForBytesWritten();
// Wait for finished
mProcess->waitForFinished();
mProcess->closeWriteChannel();
''''

QProcess doesn't show any output when it runs rsync

I start rsync in QProcess. My process runs fine (in its own terminal) if I use QProcess::startDetached() but nothing happens if I start it with QProcess:start(). The problem seems to be that QProcess can't apparently read messages from rsync and write it to the output window.
I have connect this signal in constructor.
MainWindow::~MainWindow()
{
process = new QProcess(this);
connect( process, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadyReadStandardOutput() ) );
}
Later on button clicked I call:
void MainWindow::onButton1Clicked()
{
process->start("rsync -a root#10.0.0.1:/path/ /rsync_folder");
//process->start("ping 10.0.0.01"); // this works for testing and I see output but not the above.
}
When rsync starts, it prints a message and ask for password..none of it is received by my QProcess but the ping message are received..what could be possibly wrong here?
The above grieving line also works directly on windows 7 command line but it just doesn't seem to show any progress in QProcess.
Update
Here is how I displaying the output.
void MainWindow::onReadyReadStandardOutput()
{
qDebug() << process->readAllStandardOutput();
}
http://doc.qt.io/qt-5/qprocess.html#communicating-via-channels
Did you remember to link to and check the standard error channel?
http://doc.qt.io/qt-5/qprocess.html#readAllStandardError
That has fixed it for me in the past for some QProcesses I have started.
Another way I've done it, is to use QProcess::startDetached();
Hope that helps.
My research shows that rsync probably behaves like scp which accordingly this answer doesn't generate output when it is redirected.

Evaluate output of a background linux command with C++ or Bash/Shell Script

Question: Using C++ or a bash/shell script, how can I evaluate output of a long running linux process?
Example:
root#example.com~# iw event
(This command will run until manually killed.)
(It will output data that I will want to read and parse line by line.)
What is the most efficient way to evaluate the std output of this command when a new line is added to its buffer?
For example: iw event will output a line that says:
new station: 0e:0e:20:2d:20
I want to detect "new station" and run another command with the mac address. IE:
./myProgram -mac 0e:0e:20:2d:20
Thanks!
If you run the command as shown, all output will go to stdout and display on the terminal. To capture the output you have a few options:
Pipe the output to your monitor program, as in iw events | yourmonitorprogram which then reads stdin. iw should probably be modified to use unbuffered output.
Write the output of iw to a file and then use the same technique as the tail -f command to poll the file periodically
Have iw write to a named pipe or socket and have your monitor program read from that pipe or socket. This option requires modification to iw.
The simplest option is the first one