Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to implemet "| tee " in "system" implementation in QProcess



  • Since this is a code question , I am starting new thread. .
    The attached code replaces "system" call in QProcess
    The "| tee -a" appends the command to the /tmp/temp" file,
    BUT it does not "tee" to the QTCreator console.
    It does it in system call.

    system("hcitool dev | tee -a /tmp/temp ");

     OProcess.start("/bin/sh", QStringList() << "-c" << "hcitool dev  | tee -a  /tmp/temp");
    OProcess.waitForFinished();
    OProcess.start("/bin/sh", QStringList() << "-c" << "hcitool dev  | tee -a  /tmp/temp");
    OProcess.waitForFinished();
    
    

  • Lifetime Qt Champion

    Hi,

    As already suggested in one of your other thread:

    • Read the content of your QProcess standard output
    • Use QFile to append said content to the file


  • I think @SGaist approach is probably the best (when the process has finished, use QProcess::readAllStandardOutput(), use the typical methods in Qt to write data to a file). Also, note that QProcess has a method to specify a file to redirect standard out to, but in the documentation, it states that you will not have further access to the standard output from QProcess methods:

    Redirects the process' standard output to the file fileName. When the redirection is in place, the standard output read channel is closed: reading from it using read() will always fail, as will readAllStandardOutput().

    I think this is a further indication that @SGaist's approach is the one to take.


  • Lifetime Qt Champion

    @mchinand I forgot about that method ! Thanks for the reminder.

    If @AnneRanch changes the open mode to append then it will do exactly what she wants in a simpler way than what I suggested. However, there's indeed the loss of dumping the content to qDebug but that might not be of interest in this case.



  • @AnneRanch said in How to implemet "| tee " in "system" implementation in QProcess:

    BUT it does not "tee" to the QTCreator console.

    Not that the OP seems to ever read/act on my posts, but at least it's here for anyone else who actually does. This can be done in Qt's QProcess to mimic what system() does via:

    connect(&process, &QProcess::readyReadStandardOutput, this, &SomeClass::onReadyReadStandardOutput);
    
    void SomeClass::onReadyReadStandardOutput()
    {
        QByteArray output;
        output = process.readAllStandardOutput();
        fwrite(output.data(), 1, output.length(), stdout);
        fflush(stdout);
    }
    

    Now the process' standard output will appear in the application's stdout --- the Application Output tab in Qt Creator --- as soon as it is available, while the subprocess is running.

    If you want the subprocess' stderr as well, either write a corresponding for SomeClass::onReadyReadStandardError() or set the process.setProcessChannelMode(QProcess::MergedChannels);



  • the long and the short of it is to NOT implement shell pipes or redirects in a system() call. Do your command line in a shell script and call the shell script via system().



  • @Kent-Dorfman
    I do not agree with this. By the time you choose to create a shell script to do the redirection symbol handling, you might as well use the -c argument to /bin/sh or /bin/bash. Creating the correct shell script, making it take the desired runtime parameters, and most importantly distributing/installing the script in the right place with the right permissions is itself problematic.

    (Having said that, a different plus point for a shell script is if at a later date or site you find you would like to change the commands or arguments it executes the end-user can edit it, instead of having them hard-coded into the program. It's just that it's more work to get it installed right.)

    The best way for this particular command is not to need to do any redirection on the command-line. Instead use QFile to manage the redirection in the calling application. Or maybe use

    QProcess::setStandardOutputFile(const QString &fileName, QIODevice::OpenMode mode = Truncate)
    

    with mode set to QIODevice::Append if desired.

    Personally by the time I am using Qt I would rather use its QProcess than the C library system() call, as I have more flexibility in its behaviour, especially in a UI application.


Log in to reply