Qt使用libssh2库远程执行命令

目录

先贴代码

mainwindow.h
[cpp]
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include <libssh2.h> namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_runProgram_clicked();
private:
Ui::MainWindow *ui;
int run_program();
void closeChannel(LIBSSH2_CHANNEL *channel);
// 参照google code上remote-cmd项目的方法执行多个语句
int initSession();
int runCommand(QString command);
int uploadFileViaScp(QString a_file_path, QString remote_file_dir);
int closeSession();
QTcpSocket *socket_;
LIBSSH2_SESSION *session_;
LIBSSH2_AGENT *agent_;
};
#endif // MAINWINDOW_H
[/cpp]
mainwindow.cpp
[cpp]
#include “mainwindow.h”
#include “ui_mainwindow.h”
#include
#include
#include
#include
#include
#include
#include
//#include <libssh2_config.h> #include <libssh2.h> //#include <libssh2_sftp.h> MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
session_(0),
socket_(0),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
if(session_ && socket_)
{
closeSession();
}
delete ui;
}
void MainWindow::on_runProgram_clicked()
{
//qDebug()«run_program(); if(initSession()!=1) { qDebug()«“Init session failed!”; return; } // if(runCommand(“cd /u/hantx/wangdp/GET/GETv1.01/run;”)!=1) // { // qDebug()«“command failed!”; // } // if(runCommand(“cd /u/hantx/wangdp/GET/GETv1.01/run;./get-run.sh.bak”)!=1) // { // qDebug()«“command failed!”; // } QString file_path(“D:/project/study/Qt/Exercises/ssh/ssh_exec/ssh_exec/1.txt”); QString remote_file_dir("/cma/u/wangdp/tmp/1.txt"); if(uploadFileViaScp(file_path,remote_file_dir)!=1) { qDebug()«“command failed!”; } closeSession(); } int MainWindow::run_program() { QString host_ip(“10.20.49.131”); QString commandline(“llq”); QString user_name=ui->username->text();
QString pass_word=ui->password->text();
//———- connection ————–
int libssh2_error = libssh2_init(0);
if(libssh2_error)
{
qDebug(“libssh2_init() error: %d”, libssh2_error);
return -2;
}
QTcpSocket socket;
socket.connectToHost(host_ip, 22);
if(!socket.waitForConnected())
{
qDebug(“Error connecting to host %s”, host_ip.toLocal8Bit().constData());
return -1;
}
LIBSSH2_SESSION session = libssh2_session_init();
if(!session)
{
qDebug(“libssh2_session_init() failed”);
return -2;
}
libssh2_error = libssh2_session_startup(session, socket.socketDescriptor());
if(libssh2_error)
{
qDebug(“libssh2_session_startup() error: %d”, libssh2_error);
return -3;
}
{
/
At this point we havn’t yet authenticated. The first thing to do

  • is check the hostkey’s fingerprint against our known hosts Your app
  • may have it hard coded, may go to a file, may present it to the
  • user, that’s your call
    */
    const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
    // qDebug( “Fingerprint: “);
    // for(int i = 0; i < 20; i++) // qDebug( “%02X “, (unsigned char)fingerprint[i]); // qDebug( “\n”); } // qDebug(“Password authentication: [%s] [%s]”, user_name.toLocal8Bit().constData(), pass_word.toLocal8Bit().constData()); libssh2_userauth_list(session, user_name.toLocal8Bit().constData(), user_name.toLocal8Bit().length()); if(libssh2_userauth_password( session, user_name.toLocal8Bit().constData(), pass_word.toLocal8Bit().constData() )) { qDebug(“Password authentication failed”); socket.disconnectFromHost(); libssh2_session_disconnect(session, “Client disconnecting for error”); libssh2_session_free(session); libssh2_exit(); return -4; } // command channel //-–-–-–-–setup channel -–-–-–-–-–-–-— LIBSSH2_CHANNEL channel = NULL; channel = libssh2_channel_open_session(session); int rc; if ( channel == NULL ) { qDebug()«“Failed to open a new channel\n”; socket.disconnectFromHost(); return -1; } libssh2_channel_set_blocking(channel, 1); while ((rc=libssh2_channel_exec(channel, commandline.toLocal8Bit().constData()))==LIBSSH2_ERROR_EAGAIN ); if (rc) { return -1; } //-–-—read channel-–-–-—- int read; QByteArray byte_array; byte_array.resize(4096); char buffer=byte_array.data(); int buffer_size=byte_array.size(); while(true) { //qDebug(“libssh2_channel_read() »>”);
    {
    read = libssh2_channel_read(channel, buffer, buffer_size);
    QByteArray debug = QByteArray(buffer, read);
    qDebug()«“STDOUT: “«debug.constData(); if(LIBSSH2_ERROR_EAGAIN == read) { qDebug(“LIBSSH2_ERROR_EAGAIN”); break; } else if(read < 0) { qDebug(” error reading from channel”); closeChannel(channel); goto next_channel; } } { read = libssh2_channel_read_stderr(channel, buffer, buffer_size); QByteArray debug = QByteArray(buffer, read); qDebug()«“STDERR: “«debug.constData(); if(LIBSSH2_ERROR_EAGAIN == read) { qDebug(“LIBSSH2_ERROR_EAGAIN”); break; } else if(read < 0) { qDebug(” error reading from channel”); closeChannel(channel); goto next_channel; } } int i=0; i = libssh2_channel_eof(channel); if(i) { qDebug(“libssh2_channel_eof %i”, i); closeChannel(channel); goto next_channel; } } next_channel: //-–-–-–-– clean session socket.disconnectFromHost(); // socket.waitForBytesWritten(); // socket.close(); // socket.deleteLater(); libssh2_session_disconnect(session, “Client disconnecting normally”); libssh2_session_free(session); libssh2_exit(); return 0; } void MainWindow::closeChannel(LIBSSH2_CHANNEL channel) { if(channel) { //libssh2_channel_wait_closed(channel); libssh2_channel_close(channel); libssh2_channel_free(channel); // free will auto close the channel } } int MainWindow::initSession() { QString host_ip=ui->host->text();
    QString user_name=ui->username->text();
    QString pass_word=ui->password->text();
    //———- connection ————–
    int libssh2_error = libssh2_init(0);
    if(libssh2_error)
    {
    qDebug(“libssh2_init() error: %d”, libssh2_error);
    return -2;
    }
    socket_=new QTcpSocket(this);
    socket_->connectToHost(host_ip, 22);
    if(!socket_->waitForConnected())
    {
    qDebug(“Error connecting to host %s”, host_ip.toLocal8Bit().constData());
    return -1;
    }
    session_ = libssh2_session_init();
    if(!session_)
    {
    qDebug(“libssh2_session_init() failed”);
    return -2;
    }
    libssh2_error = libssh2_session_startup(session_, socket_->socketDescriptor());
    if(libssh2_error)
    {
    qDebug(“libssh2_session_startup() error: %d”, libssh2_error);
    return -3;
    }
    {
    /
    At this point we havn’t yet authenticated. The first thing to do
  • is check the hostkey’s fingerprint against our known hosts Your app
  • may have it hard coded, may go to a file, may present it to the
  • user, that’s your call
    */
    // const char fingerprint = libssh2_hostkey_hash(session_, LIBSSH2_HOSTKEY_HASH_SHA1);
    // qDebug( “Fingerprint: “);
    // for(int i = 0; i < 20; i++) // qDebug( “%02X “, (unsigned char)fingerprint[i]); // qDebug( “\n”); } // qDebug(“Password authentication: [%s] [%s]”, user_name.toLocal8Bit().constData(), pass_word.toLocal8Bit().constData()); libssh2_userauth_list(session_, user_name.toLocal8Bit().constData(), user_name.toLocal8Bit().length()); if(libssh2_userauth_password( session_, user_name.toLocal8Bit().constData(), pass_word.toLocal8Bit().constData() )) { qDebug(“Password authentication failed”); socket_->disconnectFromHost();
    libssh2_session_disconnect(session_, “Client disconnecting for error”);
    libssh2_session_free(session_);
    libssh2_exit();
    return -4;
    }
    return 1;
    }
    int MainWindow::runCommand(QString command)
    {
    // command channel
    //————setup channel ———————-
    LIBSSH2_CHANNEL channel = NULL;
    channel = libssh2_channel_open_session(session_);
    if ( channel == NULL )
    {
    qDebug()«“Failed to open a new channel\n”; socket_->disconnectFromHost();
    return -1;
    }
    /
    Force Data to on STDOUT and STDERR to be on seperate channels
    * read individually with *_read and *_read_stderr functions */
    libssh2_channel_handle_extended_data(channel,LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL);
    // ????
    /* Setup Keepalive to 5 seconds */
    //libssh2_keepalive_config(session_, 1, 5);
    libssh2_channel_set_blocking(channel, 1);
    {
    int rc;
    while ((rc=libssh2_channel_exec(channel, command.toLocal8Bit().constData()))==LIBSSH2_ERROR_EAGAIN );
    if (rc)
    {
    return -1;
    }
    //——-read channel———–
    int read;
    QString stdout_str;
    QString stderr_str;
    while(true)
    {
    //qDebug(“libssh2_channel_read() »>”);
    {
    QByteArray byte_array;
    byte_array.resize(4096);
    char
    buffer=byte_array.data();
    int buffer_size=byte_array.size();
    read = libssh2_channel_read(channel, buffer, buffer_size-10);
    if(read>0)
    {
    QByteArray debug = QByteArray(buffer, read);
    stdout_str.append(debug);
    }
    if(LIBSSH2_ERROR_EAGAIN == read)
    {
    qDebug(“LIBSSH2_ERROR_EAGAIN”);
    break;
    }
    else if(read < 0) { qDebug(” error reading from std channel”); closeChannel(channel); goto next_channel; } } { QByteArray byte_array; byte_array.resize(4096); char* buffer=byte_array.data(); int buffer_size=byte_array.size(); /** * 执行llq -l 命令时,此处执行时间过长,直接卡死,具体问题是什么? */ read = libssh2_channel_read_stderr(channel, buffer, buffer_size-10); if(read>0)
    {
    QByteArray debug = QByteArray(buffer, read);
    stderr_str.append(debug);
    }
    if(LIBSSH2_ERROR_EAGAIN == read)
    {
    qDebug(“LIBSSH2_ERROR_EAGAIN”);
    break;
    }
    else if(read < 0) { qDebug(” error reading from stderr channel”); closeChannel(channel); goto next_channel; } } int i = libssh2_channel_eof(channel); if(i) { //qDebug(“libssh2_channel_eof %i”, i); closeChannel(channel); goto next_channel; } } next_channel: if(!stdout_str.isEmpty()) { qDebug()«“STDOUT:\n”«stdout_str; } if(!stderr_str.isEmpty()) { qDebug()«“STDERR:\n”«stderr_str; } } //libssh2_channel_set_blocking(channel, 0); return 1; } int MainWindow::uploadFileViaScp(QString a_file_path, QString remote_file_dir) { QFile a_file(a_file_path); if(a_file.exists() && !a_file.open(QIODevice::ReadOnly|QIODevice::Text)) { qCritical()«“Can’t open the file:"«a_file_path; return -1; } //QFileInfo a_file_info(a_file); //===== LIBSSH2_CHANNEL *channel; int rc; /* Send a file via scp. The mode parameter must only have permissions! */ channel = libssh2_scp_send(session_, remote_file_dir.toLocal8Bit().constData(), 0700 & 0777, // TODO: right file access mode (libssh2_uint64_t)a_file.size()); if (!channel) { char *errmsg; int errlen; int err = libssh2_session_last_error(session_, &errmsg, &errlen, 0); qCritical()«“Unable to open a session: “«err«errmsg; closeChannel(channel); return -1; } qDebug()«“SCP session waiting to send file”; QByteArray byte_array; byte_array.resize(4096); char* buffer=byte_array.data(); char* ptr=0; int buffer_size=byte_array.size(); qint64 nread; do { //nread = fread(mem, 1, sizeof(mem), local); nread = a_file.read(buffer,buffer_size); if (nread <= 0) { /* end of file */ break; } ptr = buffer; do { /* write the same data over and over, until error or completion */ rc = libssh2_channel_write(channel, ptr, nread); if (rc < 0) { qCritical()«“ERROR “«rc; break; } else { /* rc indicates how many bytes were written this time */ ptr += rc; nread -= rc; } } while (nread); } while (1); qDebug()«“Sending EOF”; libssh2_channel_send_eof(channel); fprintf(stderr, “Waiting for EOF\n”); libssh2_channel_wait_eof(channel); fprintf(stderr, “Waiting for channel to close\n”); libssh2_channel_wait_closed(channel); shutdown: // close channel closeChannel(channel); return 1; } int MainWindow::closeSession() { if(socket_->isOpen())
    socket_->disconnectFromHost();
    socket_->deleteLater();
    socket_=0;
    libssh2_session_disconnect(session_, “Client disconnecting normally”);
    libssh2_session_free(session_);
    libssh2_exit();
    return 1;
    }
    [/cpp]
    mianwindow.ui
    [xml]

参考

1. remote-cmd 项目:使用libssh2库执行多条语句。执行命令的代码文件: