QProcess not firing readyRead() or readyReadStandardOutput() signals
-
Hi Qt Community,
I am currently working on an app that will be monitoring the journalctl of the linux system, and display a popup when a specific line from another tool will be logged in it.
I am trying to reproduce a command via QProcess which works when directly in terminal. I want to perform a read of the journal every few seconds.
journalctl -q -u aktualizr* | grep "Update available"
If data with this filter exists, then I want to display a popup on my application to indicate to the user that said process has been initiated.
See below the code I'm working on:
#include <QDebug> #include <QProcess> // Check journalctl every 3 seconds #define UPDATES_CHECK_CYCLE 3000 UpdatesWorker::UpdatesWorker(QObject *parent) : QObject(parent) { // All constructor code has been moved the the init function (slot) so that it can be called after this object is assigned a thread in order to make sure everything has the correct thread scope. } void UpdatesWorker::initUpdatesChecker() { m_processUpdatesChecker = new QProcess(); connect(m_processUpdatesChecker, SIGNAL(readyRead()), this, SLOT(updateInfoReceived())); // Set up timer to check journalctl file at a fixed interval updatesCheckTimer = new QTimer(); updatesCheckTimer->setSingleShot(true); updatesCheckTimer->setInterval(UPDATES_CHECK_CYCLE); connect(updatesCheckTimer, SIGNAL(timeout()), SLOT(checkUpdates())); updatesCheckTimer->start(); } // Every 3 seconds, this function will be called and execute the journalctl read and filtering void UpdatesWorker::checkUpdates(){ if(m_processUpdatesChecker->state() == QProcess::Running || m_processUpdatesChecker->state() == QProcess::Starting){ m_processUpdatesChecker->close(); } else{ qDebug() << "Checking journal" << Qt::endl; m_processUpdatesChecker->start("/bin/sh", QStringList() << "-c" << "'journalctl -q -u aktualizr* | grep \"Update available\"'"); } updatesCheckTimer->start(); } // If the search filter returns something, this function should be called and send a signal to the UI to display a popup void UpdatesWorker::updateInfoReceived() { qDebug() << "Update initiated" << Qt::endl; updatesCheckTimer->stop(); SystemManager::Instance()->signalUpdateInitiated(); }
As of right now, the check every 3 seconds is performed correctly, but I am unable to make the app fire the readyRead() signal in order to trigger the function updateInfoReceived(). I've looked up doc and tried to use the signal readyReadStandardOutput() instead, but still nothing. Manually executing the line in terminal shows the filtered output I'm looking for.
I've tried to follow similar posts where the same concept was solved, but I can't seem to identify what I'm missing.
Thanks in advance!
-
Hi Qt Community,
I am currently working on an app that will be monitoring the journalctl of the linux system, and display a popup when a specific line from another tool will be logged in it.
I am trying to reproduce a command via QProcess which works when directly in terminal. I want to perform a read of the journal every few seconds.
journalctl -q -u aktualizr* | grep "Update available"
If data with this filter exists, then I want to display a popup on my application to indicate to the user that said process has been initiated.
See below the code I'm working on:
#include <QDebug> #include <QProcess> // Check journalctl every 3 seconds #define UPDATES_CHECK_CYCLE 3000 UpdatesWorker::UpdatesWorker(QObject *parent) : QObject(parent) { // All constructor code has been moved the the init function (slot) so that it can be called after this object is assigned a thread in order to make sure everything has the correct thread scope. } void UpdatesWorker::initUpdatesChecker() { m_processUpdatesChecker = new QProcess(); connect(m_processUpdatesChecker, SIGNAL(readyRead()), this, SLOT(updateInfoReceived())); // Set up timer to check journalctl file at a fixed interval updatesCheckTimer = new QTimer(); updatesCheckTimer->setSingleShot(true); updatesCheckTimer->setInterval(UPDATES_CHECK_CYCLE); connect(updatesCheckTimer, SIGNAL(timeout()), SLOT(checkUpdates())); updatesCheckTimer->start(); } // Every 3 seconds, this function will be called and execute the journalctl read and filtering void UpdatesWorker::checkUpdates(){ if(m_processUpdatesChecker->state() == QProcess::Running || m_processUpdatesChecker->state() == QProcess::Starting){ m_processUpdatesChecker->close(); } else{ qDebug() << "Checking journal" << Qt::endl; m_processUpdatesChecker->start("/bin/sh", QStringList() << "-c" << "'journalctl -q -u aktualizr* | grep \"Update available\"'"); } updatesCheckTimer->start(); } // If the search filter returns something, this function should be called and send a signal to the UI to display a popup void UpdatesWorker::updateInfoReceived() { qDebug() << "Update initiated" << Qt::endl; updatesCheckTimer->stop(); SystemManager::Instance()->signalUpdateInitiated(); }
As of right now, the check every 3 seconds is performed correctly, but I am unable to make the app fire the readyRead() signal in order to trigger the function updateInfoReceived(). I've looked up doc and tried to use the signal readyReadStandardOutput() instead, but still nothing. Manually executing the line in terminal shows the filtered output I'm looking for.
I've tried to follow similar posts where the same concept was solved, but I can't seem to identify what I'm missing.
Thanks in advance!
Hi,
Usually, the culprit is the pipe. The solution is to chain two QProcess (the output of the first sent to the input of the second) however, in your case, you could parse the output of journalctl directly in your application.
-
Hi,
Usually, the culprit is the pipe. The solution is to chain two QProcess (the output of the first sent to the input of the second) however, in your case, you could parse the output of journalctl directly in your application.
Hi @SGaist ,
I've attempted to chain two QProcess instead of using pipe as per the example here: QProcess - setStandardOutputProcess
However the signal still didn't fire.
To debug further, I simplified the command to remove the grep part, so the process call is now only
journalctl -q -u aktualizr*
, which outputs a bunch of results via terminal, as expected.Then, implementing into the code like so:
else{ qDebug() << "Checking journal" << Qt::endl; m_processUpdatesChecker->start("journalctl", QStringList() << "-q" << "-u aktualizr*"); }
But I still get no readyRead signals.
Performing a readAllStandardOutput() and readAllStandardError() outputs nothing either.
-
Hi @SGaist ,
I've attempted to chain two QProcess instead of using pipe as per the example here: QProcess - setStandardOutputProcess
However the signal still didn't fire.
To debug further, I simplified the command to remove the grep part, so the process call is now only
journalctl -q -u aktualizr*
, which outputs a bunch of results via terminal, as expected.Then, implementing into the code like so:
else{ qDebug() << "Checking journal" << Qt::endl; m_processUpdatesChecker->start("journalctl", QStringList() << "-q" << "-u aktualizr*"); }
But I still get no readyRead signals.
Performing a readAllStandardOutput() and readAllStandardError() outputs nothing either.
Did you connect the error signals as well ?
By the way, you did not completely split the arguments, this might also be part of the issue.
-
Hi @SGaist ,
I've attempted to chain two QProcess instead of using pipe as per the example here: QProcess - setStandardOutputProcess
However the signal still didn't fire.
To debug further, I simplified the command to remove the grep part, so the process call is now only
journalctl -q -u aktualizr*
, which outputs a bunch of results via terminal, as expected.Then, implementing into the code like so:
else{ qDebug() << "Checking journal" << Qt::endl; m_processUpdatesChecker->start("journalctl", QStringList() << "-q" << "-u aktualizr*"); }
But I still get no readyRead signals.
Performing a readAllStandardOutput() and readAllStandardError() outputs nothing either.
@Anthony-Abboud
Both the issues @SGaist has mentioned. And when do you callreadAllStandardError()
, do you wait for the process to finish first?m_processUpdatesChecker->start("/bin/sh", QStringList() << "-c" << "'journalctl -q -u aktualizr* | grep \"Update available\"'");
Enclosing the argument to
-c
inside its own'
s (single-quotes) is wrong. Remove those to make this work.m_processUpdatesChecker->start("journalctl", QStringList() << "-q" << "-u aktualizr*");
-u aktualizr*
should not be a single argument.