How to Execute SCP command to transfer files to a target machine
-
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
-
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@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.
-
@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);
-
@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);
@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.
-
@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??@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); }
-
@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); }
-
@moyin QProcess instance (process) is emitting the signal, not you. I already posted links to documentation, you should read it...
#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. -
#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.@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.
-
@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.
-
@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.
@moyin Connect a slot to http://doc.qt.io/qt-5/qprocess.html#errorOccurred and see whether you get any error.
-
@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.
-
@moyin Connect a slot to http://doc.qt.io/qt-5/qprocess.html#errorOccurred and see whether you get any error.
@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 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); }
-
@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);
@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. -
@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.@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.
-
@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.
@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?