How to Execute SCP command to transfer files to a target machine



  • Actually i tried by taking ip, ssh_username, and sshh_password as input from GUI input.
    QProcess OProcess ;
    QString Command = "scp" ; //Contains the command to be executed
    QStringList params;
    params.append("/home/span51/Desktop/readme.txt");
    params.append("username@laptop:Desktop/" ); OProcess.start("scp",params,QIODevice::ReadWrite); //Starts execution of command



  • Hi @moyin

    What is exactly your problem?

    Just as observation i think that according to your code, using startDetached is more appropriate than start

    Just replace this line:

    OProcess.start("scp",params,QIODevice::ReadWrite); //Starts execution of command
    

    to

    OProcess.startDetached("scp",params); //Starts execution of command
    

  • Moderators

    @moyin said in How to Execute SCP command to transfer files to a target machine:

    username@laptop:Desktop/

    this path is invalid. You probably mean

    username@laptop:/home/username/Desktop/
    

    Also connect a slot to http://doc.qt.io/qt-5/qprocess.html#errorOccurred signal to get more information. And read the stdout and stderr of the process to see what it says.



  • @jsulm i need to redirect stdOut and stdError to a textedit.
    i tried this but not succeed.

    proc.startDetached(command,params,QIODevice::ReadWrite) ;

    QString StdOut      =   proc.readAllStandardOutput();  //Reads standard output
    QString StdError    =   proc.readAllStandardError();   //Reads standard error
    
    ui->textEdit_Standard_output->setText(StdOut);
    ui->textEdit_Standard_output->setText(StdError);

  • Moderators

    @moyin This is not how it works. You need to connect a slot to http://doc.qt.io/qt-5/qprocess.html#readyReadStandardError and http://doc.qt.io/qt-5/qprocess.html#readyReadStandardOutput signals and read both there.



  • @jsulm can't i use

    OProcess.start("scp",params,QIODevice::ReadWrite); //Starts execution of command
    instead??


  • Moderators

    @moyin I don't understand what you mean. You need first to start the process, so yes you need to call start. Then, if you want to get stdout and stderr output of that process you need to connect a slot to those two signals I mentioned (you need the signal because you do not know when you will get output from the process, so you cannot just call readAllStandardOutput() at some random point).

    // Make process a class member because you need it in the slot bellow and because it would be deleted as soon
    // as it gets out of scope!
    class MainWindow
    {
    private:
        QProcess process;
    }
    ...
    QString command = "scp" ; //Contains the command to be executed
    QStringList params;
    params.append("/home/span51/Desktop/readme.txt");
    params.append("username@laptop:Desktop/" ); // FIX THE PATH HERE AS IT IS INVALID!
    connect(process, SIGNAL(readyReadStandardError(), this, SLOT(readOutput()));
    connect(process, SIGNAL(readyReadStandardOutput(), this, SLOT(readOutput()));
    process.start(command, params, QIODevice::ReadWrite); //Starts execution of command
    ...
    void MainWindow::readOutput()
    {
        QString StdOut proc.readAllStandardOutput();  //Reads standard output
        QString StdError    =   proc.readAllStandardError();
        ui->textEdit_Standard_output->setText(StdOut);
        ui->textEdit_Standard_output->setText(StdError);
    }
    


  • @jsulm where u emitting the signal here??


  • Moderators

    @moyin QProcess instance (process) is emitting the signal, not you. I already posted links to documentation, you should read it...



  • @jsulm

    #include "transfer.h"
    #include "ui_transfer.h"
    #include <sstream>
    #include <QProcess>
    #include <iostream>
    #include <QDebug>
    #include <QFileDialog>
    #include <QtWidgets>

    Transfer::Transfer(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Transfer)
    {
    ui->setupUi(this);
    }

    Transfer::~Transfer()
    {
    delete ui;
    }

    void Transfer::on_pushButton_Go_clicked()
    { proc = new QProcess() ;
    QString command = "scp" ;
    QString ip = ui->lineEdit_IP_Address->text() ;
    QString username = ui->lineEdit_SSH_username->text() ;
    QString dest_path = ui->lineEdit_TransferToTarget_DestinationFolder->text() ;
    QString source_path = ui->lineEdit_TransferToTarget_SourcePath->text() ;
    std::stringstream s ;
    s << username.toStdString() << "@" << ip.toStdString() << ":" << dest_path.toStdString();
    std::cout << s.str() << std::endl ;
    QStringList params ;
    params.append(source_path) ;
    params.append(QString::fromStdString(s.str())) ;
    qDebug() << params ;
    // params.append("/home/span51/Desktop/readme.txt");
    // params.append("spanidea@192.168.1.26:/home/spanidea/test" );
    connect(this, SIGNAL(readyReadStandardError()), this, SLOT(readOutput()));
    connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
    proc->startDetached(command,params) ;

    /* QString StdOut = proc.readAllStandardOutput(); //Reads standard output
    QString StdError = proc.readAllStandardError(); //Reads standard error
    std::cout<<"\n Printing the standard output..........\n";
    std::cout<<endl<<StdOut.toStdString();
    std::cout<<"\n Printing the standard error..........\n";
    std::cout<<endl<<StdError.toStdString();
    */
    }

    void Transfer::on_pushButton_choosefile_transferTotarget_clicked()
    {
    QString filepath = QFileDialog::getOpenFileName(this, tr("Transfer file"), "/home","Config_Files(*.c)") ;
    ui->lineEdit_TransferToTarget_SourcePath->setText(filepath);
    }

    void Transfer::on_pushButton_Std_output_clear_clicked()
    {
    ui->textEdit_Standard_output->clear() ;
    }

    void Transfer::on_checkBox_Show_Password_clicked(bool checked)
    {
    if (checked)
    ui->lineEdit_SSH_password->setEchoMode(QLineEdit::Normal);
    else
    ui->lineEdit_SSH_password->setEchoMode(QLineEdit::Password);
    }

    void Transfer::readOutput()
    {
    QString StdOut = proc->readAllStandardOutput(); //Reads standard output
    QString StdError = proc->readAllStandardError(); // Reads standard error
    ui->textEdit_Standard_output->setText(StdOut);
    ui->textEdit_Standard_output->setText(StdError);
    }

    its building successfully, nothing printing on textedit can find some thing into this.
    while debugging i saw slot function is not getting called.


  • Moderators

    @moyin said in How to Execute SCP command to transfer files to a target machine:

    connect(this, SIGNAL(readyReadStandardError()), this, SLOT(readOutput()));
    connect(this, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));

    You should read more carefully. You need to connect the signals from the PROCESS not from this!

    connect(process, SIGNAL(readyReadStandardError(), this, SLOT(readOutput()));
    connect(process, SIGNAL(readyReadStandardOutput(), this, SLOT(readOutput()));
    

    You should also connect a slot to http://doc.qt.io/qt-5/qprocess.html#errorOccurred and print errors you get to be able to find issues faster.



  • @jsulm i tried this also,

    connect(proc, SIGNAL(readyReadStandardError()), this, SLOT(readOutput()));
    connect(proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
    proc->startDetached(command,params) ;

    but same result, nothing will be printing on textedit.


  • Moderators

    @moyin Connect a slot to http://doc.qt.io/qt-5/qprocess.html#errorOccurred and see whether you get any error.


  • Moderators

    @moyin said in How to Execute SCP command to transfer files to a target machine:

    ui->textEdit_Standard_output->setText(StdOut);
    ui->textEdit_Standard_output->setText(StdError);

    If StdError is empty, then you are effectively overwriting your StdOut. Consider doing this instead:

    ui->textEdit_Standard_output->setText(ui->textEdit_Standard_output->text() + StdOut + StdError);
    

    And please use code tags when writing on this forum, it makes reading the code much easier.



  • @jsulm i tried this, it does't works.

        connect(&proc, SIGNAL(readyReadStandardError()), this, SLOT(readOutput()));
        connect(&proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
        connect(&proc, SIGNAL(errorOccurred()), this, SLOT(readOutput()));
        proc.startDetached(command,params) ;
    

    And did changes in readoutput() also,

        ui->textEdit_Standard_output->setText(ui->textEdit_Standard_output->toPlainText() + StdOut + StdError);
    
    


  • @jsulm @sierdzio i'm sharing my .h and .cpp files as well it may help u to understand my problem.

    transfer.h

    #ifndef TRANSFER_H
    #define TRANSFER_H
    
    #include <QDialog>
    #include <QProcess>
    
    namespace Ui {
    class Transfer;
    }
    
    class Transfer : public QDialog
    {
        Q_OBJECT
    
    public:
        explicit Transfer(QWidget *parent = 0);
        ~Transfer();
    
    private slots:
        void on_pushButton_Go_clicked();
    
        void on_pushButton_choosefile_transferTotarget_clicked();
    
        void on_pushButton_Std_output_clear_clicked();
    
        void on_checkBox_Show_Password_clicked(bool checked);
    
        void readOutput() ;
    
    private:
        Ui::Transfer *ui;
        QProcess proc ;
    /*
    signals:
        void readyReadStandardOutput() ;
        void readyReadStandardError() ;
    */
    };
    
    #endif // TRANSFER_H
    
    

    transfer.cpp

    #include "transfer.h"
    #include "ui_transfer.h"
    #include <sstream>
    #include <QProcess>
    #include <iostream>
    #include <QDebug>
    #include <QFileDialog>
    #include <QtWidgets>
    
    
    Transfer::Transfer(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Transfer)
    {
        ui->setupUi(this);
    }
    
    Transfer::~Transfer()
    {
        delete ui;
    }
    
    
    void Transfer::on_pushButton_Go_clicked()
    {
        //proc = new QProcess() ;
        QString command = "scp" ;
        QString ip = ui->lineEdit_IP_Address->text() ;
        QString username = ui->lineEdit_SSH_username->text() ;
        QString dest_path = ui->lineEdit_TransferToTarget_DestinationFolder->text() ;
        QString source_path = ui->lineEdit_TransferToTarget_SourcePath->text() ;
        std::stringstream s ;
        s << username.toStdString() << "@" << ip.toStdString() << ":" << dest_path.toStdString();
        std::cout << s.str() << std::endl ;
        QStringList params ;
        params.append(source_path) ;
        params.append(QString::fromStdString(s.str())) ;
        qDebug() << params ;
        //    params.append("/home/span51/Desktop/readme.txt");
        //    params.append("spanidea@192.168.1.26:/home/spanidea/test" );
        connect(&proc, SIGNAL(readyReadStandardError()), this, SLOT(readOutput()));
        connect(&proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
        connect(&proc, SIGNAL(errorOccurred()), this, SLOT(readOutput()));
        proc.startDetached(command,params) ;
    
    /*    QString StdOut      =   proc.readAllStandardOutput();  //Reads standard output
        QString StdError    =   proc.readAllStandardError();   //Reads standard error
        std::cout<<"\n Printing the standard output..........\n";
        std::cout<<endl<<StdOut.toStdString();
        std::cout<<"\n Printing the standard error..........\n";
        std::cout<<endl<<StdError.toStdString();
    */
    }
    
    void Transfer::on_pushButton_choosefile_transferTotarget_clicked()
    {
        QString filepath = QFileDialog::getOpenFileName(this, tr("Transfer file"), "/home","Config_Files(*.c)") ;
        ui->lineEdit_TransferToTarget_SourcePath->setText(filepath);
    }
    
    void Transfer::on_pushButton_Std_output_clear_clicked()
    {
        ui->textEdit_Standard_output->clear() ;
    }
    
    void Transfer::on_checkBox_Show_Password_clicked(bool checked)
    {
        if (checked)
            ui->lineEdit_SSH_password->setEchoMode(QLineEdit::Normal);
        else
            ui->lineEdit_SSH_password->setEchoMode(QLineEdit::Password);
    }
    
    void Transfer::readOutput()
    {
        QString StdOut = proc.readAllStandardOutput();  //Reads standard output
        QString StdError = proc.readAllStandardError(); // Reads standard error
    
    //    ui->textEdit_Standard_output->setText(StdOut);
    //    ui->textEdit_Standard_output->setText(StdError);
        ui->textEdit_Standard_output->setText(ui->textEdit_Standard_output->toPlainText() + StdOut + StdError);
    }
    
    

  • Moderators

    @moyin You again did not read documentation, right? http://doc.qt.io/qt-5/qprocess.html#errorOccurred
    Else you would see that errorOccurred() has a parameter.
    This connect cannot succeed (you should see a warning at runtime):

    connect(&proc, SIGNAL(errorOccurred()), this, SLOT(readOutput()));
    

    You need to use another slot with QProcess::ProcessError error parameter and print out its value.



  • @jsulm i can transfer file successfully to the target machine without errors. but wanted to redirect logs whatever (stdout,stderr, etc..,) to textedit. than
    why should go for QProcess::ProcessError.


  • Moderators

    @moyin Then check whether these connects actually were successful:

    qDebug() << connect(&proc, SIGNAL(readyReadStandardError()), this, SLOT(readOutput()));
    qDebug() << connect(&proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
    

    Place a qDebug() in your readOutput() to print something out to see whether the slot is actually called.



  • @jsulm i mentioned u already that, while debug if i put break point at or in readoutput() that will stop at break point so it means slot is not getting called.


  • Moderators

    @moyin said in How to Execute SCP command to transfer files to a target machine:

    while debug if i put break point at or in readoutput() that will stop at break point so it means slot is not getting called

    sorry, I'm confused: if it stops at the break point inside readOutput() then it means that it is actually called.

    Try this:

    void Transfer::readOutput()
    {
        QString StdOut = proc.readAllStandardOutput();  //Reads standard output
        QString StdError = proc.readAllStandardError(); // Reads standard error
        qDebug() << StdOut;
        qDebug() << StdError;
    //    ui->textEdit_Standard_output->setText(StdOut);
    //    ui->textEdit_Standard_output->setText(StdError);
        ui->textEdit_Standard_output->setText(ui->textEdit_Standard_output->toPlainText() + StdOut + StdError);
    }
    

    Do you see anything in Application Output?



  • @moyin said in How to Execute SCP command to transfer files to a target machine:

    that will stop

    sorry correction "that will not stop at breakpoint"


  • Moderators

    @moyin said in How to Execute SCP command to transfer files to a target machine:

    proc.startDetached(command,params) ;

    Hm, startDetached() is a static call, so attaching any signals to it won't work, right? Shouldn't start() be used here instead? Just a thought, I have not analysed this code in-depth.



  • @jsulm its printing true for both

    qDebug() << connect(&proc, SIGNAL(readyReadStandardError()), this, SLOT(readOutput()));
    qDebug() << connect(&proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));```
    
    qDebug() in readOutput() is not printing any thing.
    
    
    

  • Moderators

    @moyin This is your problem:

    proc.startDetached(command,params) ;
    

    startDetached() is a static method! So you start your process, but it is not managed by the proc instance! Use start() instead:

    proc.start(command, params);
    


  • @jsulm i tried that also but failed.


  • Moderators

    @moyin In what way failed? Same issue? Slot still not called?



  • @jsulm sorry, failed in the sense not able to print the logs into textEdit.



  • @jsulm yes slot is not getting called itself.



  • @jsulm
    Slot still not called? Yes still not called.


  • Moderators

    @moyin Can you post your current code?



  • @moyin
    I'm lost as to where you're at.

    But at least at one point you were told to use QProcess::startDetached() rather than QProcess:start(). I believe (untested by me, as usual, could be putting my neck on the line...) that you cannot properly redirect process input/output and/or get signals for input/output if you run the child process detached...?


  • Moderators

    @JNBarchan This was already mentioned, but @moyin says that it isn't working even after changing to start().
    There most be still something in the code, that's why I asked for the current code.



  • @jsulm
    OK, as long he is not trying startDetached that's good...

    FWIW, I happen to just be working on my own Dialog which spawns a sub-process (QProcess::start()), gets its output via signals, and copies it into scrolling text widget, and it's all working fine for me. As one would expect!

    Purely BTW, given the command is an scp whose job is to copy the files, I wonder just what stdout/stderr output he is expecting? Has he informed us whether it's just the output that's missing/empty, or whether the whole command is not running in any case??


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.