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. capture output from shell command using QProcess in Qt6

capture output from shell command using QProcess in Qt6

Scheduled Pinned Locked Moved Solved General and Desktop
15 Posts 4 Posters 2.9k Views
  • 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.
  • G Offline
    G Offline
    GregB
    wrote on 23 Feb 2022, 15:59 last edited by
    #1

    I'm using QProcess to run shell commands and capture the output on Linux. My program worked fine when compiled with Qt 5.15, but now it's not working with Qt 6.2.3.

    Here's some example code

    QString s = "ls";
    QString output;
    process.start("sh", QStringList() << "-c" << s);
    process.waitForFinished();
    output = QString(process.readAllStandardOutput());
    output += QString(process.readAllStandardError());
    WriteLog("Output: [" + output + "]"); /* my function */
    

    The shell command always runs successfully (cp, mv, etc), but I can no longer capture the output. I do want to run the command synchronously, meaning I want to wait until the command has finished before moving on, if that makes a difference now. Has something changed in Qt6 with output? Is there a new way to capture output?

    J A 2 Replies Last reply 23 Feb 2022, 18:42
    0
    • G GregB
      23 Feb 2022, 15:59

      I'm using QProcess to run shell commands and capture the output on Linux. My program worked fine when compiled with Qt 5.15, but now it's not working with Qt 6.2.3.

      Here's some example code

      QString s = "ls";
      QString output;
      process.start("sh", QStringList() << "-c" << s);
      process.waitForFinished();
      output = QString(process.readAllStandardOutput());
      output += QString(process.readAllStandardError());
      WriteLog("Output: [" + output + "]"); /* my function */
      

      The shell command always runs successfully (cp, mv, etc), but I can no longer capture the output. I do want to run the command synchronously, meaning I want to wait until the command has finished before moving on, if that makes a difference now. Has something changed in Qt6 with output? Is there a new way to capture output?

      J Offline
      J Offline
      JonB
      wrote on 23 Feb 2022, 18:42 last edited by JonB
      #2

      @GregB said in capture output from shell command using QProcess in Qt6:

      My program worked fine when compiled with Qt 5.15, but now it's not working with Qt 6.2.3.

      This sounds depressing! Out of interest, you have no need of sh -c to run an ls, what happens if you run the ls (or /bin/ls to be sure) without the sh -c?

      Also, if I wanted to test I might get rid of the waitForFinished() and the readAll...() and try it with signals/slots, does that work?

      1 Reply Last reply
      1
      • M Offline
        M Offline
        mchinand
        wrote on 23 Feb 2022, 18:58 last edited by
        #3

        In addition to what @JonB wrote, I wonder if your Qt6 version has the fix for this QProcess security issue applied whereas your Qt5.15 version does not.

        J 1 Reply Last reply 23 Feb 2022, 19:02
        0
        • M mchinand
          23 Feb 2022, 18:58

          In addition to what @JonB wrote, I wonder if your Qt6 version has the fix for this QProcess security issue applied whereas your Qt5.15 version does not.

          J Offline
          J Offline
          JonB
          wrote on 23 Feb 2022, 19:02 last edited by
          #4

          @mchinand
          In theory I don't see that would apply (I will be proven wrong, doubtless!), but just in case: @GregB while you use sh as your command try it with /bin/sh specified instead? Personally I would always write that rather than plain sh.

          1 Reply Last reply
          2
          • G Offline
            G Offline
            GregB
            wrote on 23 Feb 2022, 20:27 last edited by
            #5

            @JonB I was using ls as an example here. Most of the commands I'm running are big long things that run other commands and pass lots of parameters and paths, and sometimes sequences of commands separated by semi-colons. So in the end, sh -c "FSL_DIR=/usr/local/fsl; source ${FSL_DIR}/setpaths.sh; program -o parameter; more commands; etc" was best.
            Running the command using QProcess isn't the issue, that works just fine. It executes, and returns just fine. But I can't capture the output like I used to.

            I'm wondering if it's a library issue, since i'm building on CentOS 8, or that QProcess in Qt6 doesn't quite work the same way as Qt5.15.

            How would one use signals/slots in a program that is not asynchronous?

            J 1 Reply Last reply 23 Feb 2022, 22:15
            0
            • G GregB
              23 Feb 2022, 20:27

              @JonB I was using ls as an example here. Most of the commands I'm running are big long things that run other commands and pass lots of parameters and paths, and sometimes sequences of commands separated by semi-colons. So in the end, sh -c "FSL_DIR=/usr/local/fsl; source ${FSL_DIR}/setpaths.sh; program -o parameter; more commands; etc" was best.
              Running the command using QProcess isn't the issue, that works just fine. It executes, and returns just fine. But I can't capture the output like I used to.

              I'm wondering if it's a library issue, since i'm building on CentOS 8, or that QProcess in Qt6 doesn't quite work the same way as Qt5.15.

              How would one use signals/slots in a program that is not asynchronous?

              J Offline
              J Offline
              JonB
              wrote on 23 Feb 2022, 22:15 last edited by
              #6

              @GregB
              I know your desired commands are complex.
              I suggested you might like to verify whether the same behaviour is observed in a simple command.
              I suggested you might like to see if the signal/slot calls (e..g readyRead...) work instead of your current code.
              Up to you.

              G 1 Reply Last reply 24 Feb 2022, 00:09
              0
              • J JonB
                23 Feb 2022, 22:15

                @GregB
                I know your desired commands are complex.
                I suggested you might like to verify whether the same behaviour is observed in a simple command.
                I suggested you might like to see if the signal/slot calls (e..g readyRead...) work instead of your current code.
                Up to you.

                G Offline
                G Offline
                GregB
                wrote on 24 Feb 2022, 00:09 last edited by
                #7

                @JonB I'll try that.

                1 Reply Last reply
                0
                • G Offline
                  G Offline
                  GregB
                  wrote on 24 Feb 2022, 15:39 last edited by
                  #8

                  Thanks @JonB . I tried the /bin/sh but that didn't work. It still runs the commands just fine, but doesn't capture the output.

                  How would I use signals/slots with this?

                  J 1 Reply Last reply 25 Feb 2022, 10:03
                  0
                  • G GregB
                    24 Feb 2022, 15:39

                    Thanks @JonB . I tried the /bin/sh but that didn't work. It still runs the commands just fine, but doesn't capture the output.

                    How would I use signals/slots with this?

                    J Offline
                    J Offline
                    JonB
                    wrote on 25 Feb 2022, 10:03 last edited by
                    #9

                    @GregB
                    If you read what I wrote I suggested you try the simplest command, e.g. a direct /bin/ls, no arguments, no /bin/sh. We are trying to eliminate sh from the issue equation.

                    For signals/slots: get rid of waitForFinished(), get rid of readAll...(), attach slots to the two readyRead...() signals, see if those receive any output.

                    1 Reply Last reply
                    0
                    • M Offline
                      M Offline
                      mchinand
                      wrote on 25 Feb 2022, 14:11 last edited by
                      #10

                      Also, what is the output you are getting now? Can you check what the stdout/stderr out is directly without using your WriteLog function? Not as a solution, but just to help debug your issue, you can try setting QProcess::setStandardOutputFile() and see what gets written to that file. Note, as the documentation says, readAllStandardOutput() will no longer work when you use this.

                      1 Reply Last reply
                      0
                      • G GregB
                        23 Feb 2022, 15:59

                        I'm using QProcess to run shell commands and capture the output on Linux. My program worked fine when compiled with Qt 5.15, but now it's not working with Qt 6.2.3.

                        Here's some example code

                        QString s = "ls";
                        QString output;
                        process.start("sh", QStringList() << "-c" << s);
                        process.waitForFinished();
                        output = QString(process.readAllStandardOutput());
                        output += QString(process.readAllStandardError());
                        WriteLog("Output: [" + output + "]"); /* my function */
                        

                        The shell command always runs successfully (cp, mv, etc), but I can no longer capture the output. I do want to run the command synchronously, meaning I want to wait until the command has finished before moving on, if that makes a difference now. Has something changed in Qt6 with output? Is there a new way to capture output?

                        A Offline
                        A Offline
                        artwaw
                        wrote on 25 Feb 2022, 14:37 last edited by artwaw
                        #11

                        @GregB I just wrote (Qt 6.2.3) similar code to capture output of which (I needed to locate ssh client).
                        This worked for me (simplified and version in progress, my shell is zsh):

                        QProcess check;
                        check.start("zsh",QStringList({"-c","which ssh"}));
                        if (!check.waitForStarted()) {
                            QMessageBox::warning(this,"Warning","Could not run detection routine, you have to specify SSH runtime manually");
                            qDebug() << check.errorString();
                        } else {
                            check.waitForReadyRead();
                            qDebug() << check.readAllStandardOutput();
                            check.write("exit");
                            check.waitForFinished();
                        }
                        

                        If you worry about capturing errors you can avoid double checking of error channel by issuing QProcess::setProcessChannelMode(QProcess::MergedChannels);

                        As for the why the way you did it stopped to work I have no answer though.

                        For more information please re-read.

                        Kind Regards,
                        Artur

                        1 Reply Last reply
                        2
                        • G Offline
                          G Offline
                          GregB
                          wrote on 25 Feb 2022, 22:06 last edited by
                          #12

                          @artwaw Thanks for testing that bit of code. I figured out the issue and it appears to be a bug in Qt6. I eventually got my code to work, but only on a different OS. I tested the following combinations:

                          CentOS 8 + Qt 5.15 --> works correctly
                          CentOS Stream 8 + Qt 5.15 --> works correctly
                          CentOS Stream 8 + Qt 6.2 --> doesn't work (this is my current production platform)
                          Rocky Linux 8 + Qt 6.2 --> works correctly

                          I reported the bug to Qt. It's a weird bug and one that was only noticed after a few weeks. Unfortunately my production server is CentOS Stream 8, and I can't revert to a previous version of my program. So the best course is to upgrade the production server to Rocky Linux 8. That'll fix the issue for me :-)

                          Thank you all for your help!

                          1 Reply Last reply
                          0
                          • M Offline
                            M Offline
                            mchinand
                            wrote on 25 Feb 2022, 22:33 last edited by
                            #13

                            If there is one, can you post the link to the bugreport?

                            1 Reply Last reply
                            0
                            • G Offline
                              G Offline
                              GregB
                              wrote on 26 Feb 2022, 15:53 last edited by
                              #14

                              @mchinand https://bugreports.qt.io/browse/QTBUG-101275

                              J 1 Reply Last reply 28 Feb 2022, 09:47
                              0
                              • G GregB
                                26 Feb 2022, 15:53

                                @mchinand https://bugreports.qt.io/browse/QTBUG-101275

                                J Offline
                                J Offline
                                JonB
                                wrote on 28 Feb 2022, 09:47 last edited by
                                #15

                                @GregB
                                IMHO it's a shame you did not try either of the suggestion I made in earlier post:

                                @JonB said in capture output from shell command using QProcess in Qt6:

                                @GregB
                                If you read what I wrote I suggested you try the simplest command, e.g. a direct /bin/ls, no arguments, no /bin/sh. We are trying to eliminate sh from the issue equation.
                                For signals/slots: get rid of waitForFinished(), get rid of readAll...(), attach slots to the two readyRead...() signals, see if those receive any output.

                                Doing so would tell us/you whether (a) it has anything to do with shell or not and (b) whether it has anything to do with the waitFor...() calls or not. It may well be that your issue still occurs, but al least we would know.

                                1 Reply Last reply
                                0

                                3/15

                                23 Feb 2022, 18:58

                                topic:navigator.unread, 12
                                • Login

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