Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QProcess not firing readyRead() or readyReadStandardOutput() signals
Forum Updated to NodeBB v4.3 + New Features

QProcess not firing readyRead() or readyReadStandardOutput() signals

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 3 Posters 703 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Anthony Abboud
    wrote on last edited by
    #1

    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!

    SGaistS 1 Reply Last reply
    0
    • A Anthony Abboud

      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!

      SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      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.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      A 1 Reply Last reply
      1
      • SGaistS SGaist

        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.

        A Offline
        A Offline
        Anthony Abboud
        wrote on last edited by
        #3

        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.

        SGaistS JonBJ 2 Replies Last reply
        0
        • A Anthony Abboud

          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.

          SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          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.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1
          • A Anthony Abboud

            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.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @Anthony-Abboud
            Both the issues @SGaist has mentioned. And when do you call readAllStandardError(), 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.

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved