📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

文字列「__FORCETOC__」を「{{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This pag…
 
(同じ利用者による、間の34版が非表示)
2行目: 2行目:
Qtにおいて、簡潔にSSH接続を確立する手順を記載する。<br>
Qtにおいて、簡潔にSSH接続を確立する手順を記載する。<br>
<br>
<br>
* libsshまたはlibssh2を使用する。
* libSSHライブラリ (LGPLライセンス) を使用する。
* QProcessクラスを使用して、外部のSSHプロセスを呼び出して接続を確立する。
* libSSH2ライブラリ (3条項BSDライセンス) を使用する。
* 他のSSHライブラリを購入する。<br>http://netsieben.com/products/ssh
* <code>QProcess</code>クラスを使用して、外部のSSHプロセスをフォークして接続を確立する。
* wolfSSH
*: wolfSSHライブラリは、wolfSSLと連携して使用する。
*: 無償版は、<u>GPL v2ライセンス</u>である。
*: 有償版は、独自ライセンスである。
*: https://wolfssl.jp/products/wolfssh/
*: Github : https://github.com/wolfSSL/wolfssh
*: wolfSSLのGithub : https://github.com/wolfSSL/wolfssl
*: <br>
*: また、wolfSSLは、IoTデバイス、組み込み向け小型デバイスにも対応した軽量のSSL/TLSライブラリである。
* QSshライブラリを使用する。
*: QSshは、QtアプリケーションにSSHとSFTPのサポートを提供する。
*: QSshプロジェクトは、過去のQt CreatorのSSHプラグインに基づいており、全てのクレジットはQt Creatorチームに帰属する。
*: ただし、現在では、Qt CreatorはOpenSSHを使用している。
*: <br>
*: https://github.com/sandsmark/QSsh
<br><br>
<br><br>


169行目: 184行目:
<br><br>
<br><br>


== 独自クラスの使用 ==
== libSSHの使用例 ==
以下の例では、公開鍵認証を使用してリモートPCへSSH接続している。<br>
<br>
<syntaxhighlight lang="make">
# .pro プロジェクトファイル
# pkg-configを使用する場合
CONFIG += link_pkgconfig
LIBS += \
    -L/<libSSHのインストールディレクトリ>/lib64 -lssh
# pkg-configを使用しない場合
LIBS += \
    -L/<libSSHのインストールディレクトリ>/lib64 -lssh
INCLUDEPATH += \
    /<libSSHのインストールディレクトリ>/include
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
#include <QCoreApplication>
#include <QMessageBox>
#include <libssh/libssh.h>
int VerifyKnownsHost(ssh_session my_ssh_session, QString &strErrMsg);
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // SSHセッションの作成
    ssh_session my_ssh_session = ssh_new();
    if (my_ssh_session == NULL) {
      // 作成に失敗した場合
      return -1;
    }
    // SSHセッションの設定
    QString host = "<リモートPCのIPアドレス または ホスト名>";
    QString user = "<リモートPCのユーザ名>";
    QString port = "<SSHポート番号  例: 22>";
 
    ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, host.toUtf8().data());
    ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, user.toUtf8().data());
    ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT_STR, port.toUtf8().data());
    // SSH接続
    int rc = ssh_connect(my_ssh_session);
    if (rc != SSH_OK) {
      // 接続に失敗した場合
      fprintf(stderr, "Error connecting to host: %s\n", ssh_get_error(my_ssh_session));
      ssh_free(my_ssh_session);
      return -1;
    }
    // ~/.sshディレクトリ等にあるファイルに記述されているサーバのIDを検証
    QString strErrMsg = "";
    if(VerifyKnownsHost(my_ssh_session, strErrMsg) < 0)
    {
      fprintf(stderr, "%s\n", strErrMsg.toUtf8().constData();
      if(my_ssh_session != nullptr)
      {
          ssh_disconnect(my_ssh_session);
          ssh_free(my_ssh_session);
      }
      return -1;
    }
    // 公開鍵認証
    // 秘密鍵の設定
    const char *private_key_path = "<秘密鍵のパス  例: /home/user/sshkey/id_rsa";
    // 秘密鍵のパスフレーズを設定していない場合
    rc = ssh_userauth_privatekey_file(my_ssh_session, nullptr, private_key_path, nullptr);
    // 秘密鍵のパスフレーズを設定している場合
    rc = ssh_userauth_privatekey_file(my_ssh_session, nullptr, private_key_path, "<秘密鍵のパスフレーズ>");
    if (rc != SSH_AUTH_SUCCESS) {
      // 認証に失敗した場合
      fprintf(stderr, "Error authenticating with private key: %s\n", ssh_get_error(my_ssh_session));
      ssh_disconnect(my_ssh_session);
      ssh_free(my_ssh_session);
      return -1;
    }
    // SSHセッションを使用して任意の処理を実行
    // scpコマンドの実行、または、リモート先で任意のコマンドの実行等
    // ...略
    // SSH接続の切断
    ssh_disconnect(my_ssh_session);
    // SSHセッションの解放
    ssh_free(my_ssh_session);
    return 0;
}
int VerifyKnownsHost(ssh_session my_ssh_session, QString &strErrMsg)
{
    // Authenticating the server.
    ssh_key srv_pubkey = {};
    if(ssh_get_server_publickey(my_ssh_session, &srv_pubkey) < 0)
    {
      strErrMsg = tr("Failed to get public key.");
      return -1;
    }
    unsigned char *hash = nullptr;
    size_t        hlen  = 0L;
    auto iRet = ssh_get_publickey_hash(srv_pubkey, SSH_PUBLICKEY_HASH_SHA256, &hash, &hlen);
    ssh_key_free(srv_pubkey);
    if(iRet < 0)
    {
      strErrMsg = tr("Failed to get public key hash.");
      return -1;
    }
    auto state = ssh_session_is_known_server(my_ssh_session);
    if(state == ssh_known_hosts_e::SSH_KNOWN_HOSTS_OK)
    {  // Authentication Successful
    }
    else if(state == ssh_known_hosts_e::SSH_KNOWN_HOSTS_CHANGED)
    {
      QString strHexa = ssh_get_hexa(hash, hlen);
      // print string in reverse order
      strErrMsg = tr("Host key for server changed:") + "<br>" +
                  tr("For security reasons, connection will be stopped.") + "<br><br>" +
                  tr("Public key hash:") + "<br>" + strHexa + "<br>" + hlen;
      ssh_clean_pubkey_hash(&hash);
      return -1;
    }
    else if(state == ssh_known_hosts_e::SSH_KNOWN_HOSTS_OTHER)
    {
      strErrMsg = tr("The host key for this server was not found but an other type of key exists.") + "<br>" +
                  tr("An attacker might change the default server key to confuse your client into") + "<br>" +
                  tr("thinking the key does not exist");
      ssh_clean_pubkey_hash(&hash);
      return -1;
    }
    else if(state == ssh_known_hosts_e::SSH_KNOWN_HOSTS_NOT_FOUND)
    {
      /* FALL THROUGH to SSH_KNOWN_HOSTS_UNKNOWN behavior */
      QString strHexa = ssh_get_hexa(hash, hlen);
      QString strAddHostMessage = tr("Could not find known host file.") + "\n" +
                                  tr("If you accept the host key here, the file will be automatically created.") + "\n\n" +
                                  tr("The server is unknown. Do you trust the host key?") + "\n" +
                                  tr("Public key hash: ") + "\n" + strHexa;
      auto ret = QMessageBox(QMessageBox::Warning, QMessageBox::tr("Add Host"), strAddHostMessage,
                              QMessageBox::Yes | QMessageBox::No, nullptr).exec();
      ssh_clean_pubkey_hash(&hash);
      if(ret == QMessageBox::No)
      {
          strErrMsg = tr("To connect, please add host key.");
          return -1;
      }
      else
      {
          iRet = ssh_session_update_known_hosts(my_ssh_session);
          if(iRet < 0)
          {
            strErrMsg = tr("Failed to update host key.");
            return -1;
          }
      }
    }
    else if(state == ssh_known_hosts_e::SSH_KNOWN_HOSTS_UNKNOWN)
    {
      QString strHexa = ssh_get_hexa(hash, hlen);
      QString strAddHostMessage = tr("The server is unknown. Do you trust the host key?") + "\n" +
                                  tr("Public key hash: ") + "\n" + strHexa;
      auto msgRet = QMessageBox(QMessageBox::Warning, QMessageBox::tr("Add Host"), strAddHostMessage,
                                QMessageBox::Yes | QMessageBox::No, nullptr).exec();
      ssh_clean_pubkey_hash(&hash);
      if(msgRet == QMessageBox::No)
      {
          strErrMsg = tr("To connect, please add host key.");
          return -1;
      }
      else
      {
          iRet = ssh_session_update_known_hosts(my_ssh_session);
          if(iRet < 0)
          {
            strErrMsg = tr("Failed to update host key.");
            return -1;
          }
      }
    }
    else if(state == ssh_known_hosts_e::SSH_KNOWN_HOSTS_ERROR)
    {
      strErrMsg = tr("There was an error in checking the host.");
      ssh_clean_pubkey_hash(&hash);
      return -1;
    }
    ssh_clean_pubkey_hash(&hash);
    return 0;
} </syntaxhighlight>
<br><br>
 
== libSSHを使用した独自クラスの使用 ==
以下に示すクラスは、クロスプラットフォームの非同期SSHおよびSCPソケットである。<br>
以下に示すクラスは、クロスプラットフォームの非同期SSHおよびSCPソケットである。<br>
このクラスは、libSSHを必要とする。(RSA鍵の受け渡しを隠したり、コマンドの応答をreadyReadシグナル経由ではなく、シングルショットで送信している)<br>
このクラスは、libSSHを必要とする。(RSA鍵の受け渡しを隠したり、コマンドの応答をreadyReadシグナル経由ではなく、シングルショットで送信している)<br>
178行目: 416行目:
<center><code><u>[[ファイル:CSSH.zip|フレームなし|中央]]</u></code></center>
<center><code><u>[[ファイル:CSSH.zip|フレームなし|中央]]</u></code></center>
<br><br>
<br><br>
== libSSH2ライブラリを使用したコマンドの使用例 ==
==== ブロッキングモード ====
以下の例では、リモート側のPCにSSH接続して、lsコマンドを実行してその結果をローカル側のPCに表示している。<br>
<br>
以下の例は、<u>ブロッキングモード</u>でlsコマンドを実行している。<br>
<br>
<syntaxhighlight lang="make">
# .pro プロジェクトファイル
# QTcpSocketを使用する場合
QT += network
# pkg-configを使用する場合
CONFIG += link_pkgconfig
LIBS += \
    -L/<libSSH2のインストールディレクトリ>/lib64 -lssh2
# pkg-configを使用しない場合
LIBS += \
    -L/<libSSH2のインストールディレクトリ>/lib64 -lssh2
INCLUDEPATH += \
    /<libSSH2のインストールディレクトリ>/include
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// main.cpp
#include <QCoreApplication>
#include <QTcpSocket>
#include <QDebug>
#include <libssh2.h>
#include "DivideByZeroException.h"
void DisConnect(QTcpSocket &sock, LIBSSH2_SESSION *session);
int  ExecCommand(QTcpSocket &sock, LIBSSH2_SESSION *session);
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    int rc  = 0;
    QTcpSocket sock;
    LIBSSH2_SESSION *session = nullptr;
    // libSSH2オブジェクトの初期化
    auto rc = libssh2_init(0);
    if (rc != 0) {
        qDebug() << "libssh2 initialization failed";
        DisConnect(sock, session);
        return -1;
    }
    // QTcpSocketクラスのインスタンスを生成して、リモートPCに接続
    sock.connectToHost(<リモートPCのIPアドレスまたはホスト名>, <リモートPCにSSH接続するポート番号>);
    // 最大10[秒]待機
    if (!sock.waitForConnected(10000)) {
      qDebug() << "SSH接続に失敗:" << socket.errorString();
      DisConnect(sock, session);
      return -1;
    }
    // SSHのセッションの初期化
    session = libssh2_session_init();
    if (!session) {
      qDebug() << "SSHのセッションの初期化に失敗";
      DisConnect(sock, session);
      return -1;
    }
    // SSHのハンドシェイク
    if (libssh2_session_handshake(session, sock.socketDescriptor()) != 0) {
      qDebug() << "SSHのハンドシェイクに失敗";
      DisConnect(sock, session);
      return -1;
    }
    // リモートPCのフィンガープリントを確認
    auto fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
    qDebug() << "リモートPCのフィンガープリント:" << fingerprint;
    // 認証方法の確認
    auto userauth_list = libssh2_userauth_list(session, "<リモートPCのユーザ名>", strlen(USERNAME));
    qDebug() << "認証方法:" << userauth_list;
    // パスワード認証を行う場合
    //if (libssh2_userauth_password(session, "<リモートPCのユーザ名>", "<リモートPCのユーザパスワード>") != 0) {
    //  qDebug() << "パスワードによる認証に失敗";
    //  return -1;
    //}
    // 公開鍵認証
    if (libssh2_userauth_publickey_fromfile(session, "<リモートPCのユーザ名>", "<公開鍵ファイルのパス>", "<秘密鍵ファイルのパス>", "<秘密鍵のパスフレーズ>") != 0) {
      qDebug() << "公開鍵認証に失敗";
      DisConnect(sock, session);
      return -1;
    }
    qDebug() << QString("Authentication succeeded.");
    // SSH接続後の処理
    // リモートPC上でls -alコマンドを実行
    rc = ExecCommand(sock, session);
    if (rc != 0) {
      DisConnect(sock, session);
      return -1;
    }
    // SSH接続の終了
    DisConnect(sock, session);
    return 0;
}
void DisConnect(QTcpSocket &sock, LIBSSH2_SESSION *session)
{
    // セッションの終了
    if (session) {
      libssh2_session_disconnect(session, "Normal Shutdown");
      libssh2_session_free(session);
      session = nullptr;
    }
    // ソケットを閉じる
    if(sock.isOpen()) {
        sock.close();
    }
    // libSSH2の終了
    libssh2_exit();
    return;
}
int ExecCommand(QTcpSocket &sock, LIBSSH2_SESSION *session)
{
    // チャンネルをオープン
    LIBSSH2_CHANNEL *channel = libssh2_channel_open_session(session);
    if (!channel) {
      qDebug() << "チャンネルのオープンに失敗";
      return -1;
    }
    // リモートPC上でls -alコマンドを実行
    if (libssh2_channel_exec(channel, "ls -la") != 0) {
      qDebug() << "コマンドの実行に失敗";
      return -1;
    }
    // ls -alコマンドの実行結果を取得
    int rc = 0;
    QByteArray buffer;
    buffer.resize(1024);  // バッファサイズを1024バイトに指定
    do {
      rc = libssh2_channel_read(channel, buffer.data(), buffer.size());
      if (rc > 0) {
          qDebug().noquote() << QString::fromUtf8(buffer.constData(), rc);
      }
      else if (rc < 0) {
          qDebug() << "Error reading channel:" << rc;
          break;
      }
    } while (rc > 0);
    // チャンネルの終了を確認
    // 終了コードおよび終了シグナルを取得して表示
    int  exitcode    = 127;
    char *exitsignal = nullptr;
    rc = libssh2_channel_close(channel);
    if (rc == 0) {
      exitcode = libssh2_channel_get_exit_status(channel);
      libssh2_channel_get_exit_signal(channel, &exitsignal, nullptr, nullptr, nullptr, nullptr, nullptr);
    }
    if (exitsignal) qDebug() << "Exit signal:" << exitsignal;
    else            qDebug() << "Exit code:" << exitcode;
    return 0;
}
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// DivideByZeroException.h
#ifndef DIVIDEBYZEROEXCEPTION_H
#define DIVIDEBYZEROEXCEPTION_H
#include <QException>
class DivideByZeroException : public QException
{
public:
    DivideByZeroException() {};
    virtual ~DivideByZeroException() {};
    const char* what() const noexcept override {
      return "Divide by zero exception";
    }
};
#endif // DIVIDEBYZEROEXCEPTION_H
</syntaxhighlight>
<br>
==== ノンブロッキングモード ====
以下の例では、リモート側のPCにSSH接続して、lsコマンドを実行してその結果をローカル側のPCに表示している。<br>
<br>
以下の例は、<u>ノンブロッキングモード</u>でlsコマンドを実行している。<br>
<u>ノンブロッキングモード</u> (シグナル / スロット) で設計する場合、libSSH2ライブラリの関数呼び出しは即座に返されて、処理がバックグラウンドで非同期に進行する。<br>
これにより、プログラムは他の処理を続行でき、必要に応じてリモートホストとの通信が完了するのを待つことができる。<br>
<br>
ノンブロッキングモードを使用する場合、特に入出力操作が発生する待ち時間を最小限に抑え、プログラムがより効率的に動作することが期待される。<br>
しかし、ノンブロッキングモードを扱う際には、非同期処理やイベント駆動型のプログラミングに慣れる必要がある。<br>
<br>
<syntaxhighlight lang="c++">
// SSHClient.hファイル
#include <QCoreApplication>
#include <QTcpSocket>
#include <QTimer>
#include <QDebug>
#include <libssh2.h>
class SSHClient : public QObject
{
    Q_OBJECT
private:
    QTcpSocket      *m_Socket;
    LIBSSH2_SESSION *m_Session;
    LIBSSH2_CHANNEL *m_Channel;
    QString        m_Host;
    quint16        m_Port;
    QString        m_User;
    QString        m_Passwaord;
    QString        m_PubKey;
    QString        m_PrivateKey;
    QString        m_Passphrase;
public:
    SSHClient(QString host, quint16 port, QString user, QString password, QObject *parent = nullptr);
    SSHClient(QString host, quint16 port, QString user,
              QString pubkey, QString privkey, QString phrase, QObject *parent = nullptr);
    ~SSHClient();
    void connectToHost();
private slots:
    void onConnected();
    void authenticateUser();
    void openChannel();
    void executeCommand();
    void onReadyRead();
    void readOutput();
    void closeChannel();
};
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// SSHClient.cppファイル
#include "SSHClient.h"
SSHClient::SSHClient(QString host, quint16 port, QString user, QString password, QObject *parent = nullptr) :
    QObject(parent), m_Session(nullptr), m_Channel(nullptr), m_Host(host), m_Port(port), m_User(user), m_Password(password)
{
    m_Socket = new QTcpSocket(this);
    connect(m_Socket, &QTcpSocket::connected, this, &SSHClient::onConnected);
    connect(m_Socket, &QTcpSocket::readyRead, this, &SSHClient::onReadyRead);
    // libSSH2ライブラリの初期化
    if (libssh2_init(0) != 0) {
      qDebug() << "libSSH2ライブラリの初期化に失敗";
      return;
    }
}
SSHClient::SSHClient(QString host, quint16 port, QString user, QString pubkey, QString privkey, QString phrase, QObject *parent = nullptr) :
    QObject(parent), m_Session(nullptr), m_Channel(nullptr),
    m_Host(host), m_Port(port), m_User(user), m_PublicKey(pubkey), m_PrivateKey(privkey), m_Passphrase(phrase)
{
    m_Socket = new QTcpSocket(this);
    connect(m_Socket, &QTcpSocket::connected, this, &SSHClient::onConnected);
    connect(m_Socket, &QTcpSocket::readyRead, this, &SSHClient::onReadyRead);
    // libSSH2ライブラリの初期化
    if (libssh2_init(0) != 0) {
      qDebug() << "libSSH2ライブラリの初期化に失敗";
      return;
    }
}
SSHClient::~SSHClient()
{
    if (m_Channel) libssh2_channel_free(m_Channel);
    if (m_Session) {
      libssh2_session_disconnect(m_Session, "Normal Shutdown");
      libssh2_session_free(m_Session);
    }
    libssh2_exit();
}
void SSHClient::connectToHost()
{
    m_Socket->connectToHost(m_Host, m_Port);
}
void SSHClient::onConnected()
{
    qDebug() << "ホストへの接続に成功";
    m_Session = libssh2_session_init();
    libssh2_session_set_blocking(m_Session, 0);
    int rc = 0;
    do {
      rc = libssh2_session_handshake(m_Session, m_Socket->socketDescriptor());
    } while (rc == LIBSSH2_ERROR_EAGAIN);
    if (rc) {
      qDebug() << "SSHのセッションの確立に失敗:" << rc;
      return;
    }
    authenticateUser();
}
void SSHClient::authenticateUser()
{
    int rc = 0;
    do {
      // パスワード認証を行う場合
      //rc = libssh2_userauth_password(m_Session,
      //                              m_User.toUtf8().constData(),
      //                              m_Password.toUtf8().constData());
      // 公開鍵認証を行う場合
      rc = libssh2_userauth_publickey_fromfile(m_Session,
                                                m_User.toUtf8().constData(),
                                                "",  // クライアントPCに秘密鍵があり、
                                                    // リモートPC側に公開鍵が設置されている場合
                                                m_PrivateKey.toUtf8().constData(),
                                                m_Passphrase.isEmpty() ? nullptr : m_Passphrase.toUtf8().constData());
    } while (rc == LIBSSH2_ERROR_EAGAIN);
    if (rc) {
      qDebug() << "認証に失敗:" << rc;
      return;
    }
    openChannel();
}
void SSHClient::openChannel()
{
    int rc = 0;
    do {
        m_Channel = libssh2_channel_open_session(m_Session);
    } while (m_Channel == nullptr && libssh2_session_last_error(m_Session, nullptr, nullptr, 0) == LIBSSH2_ERROR_EAGAIN);
    if (!m_Channel) {
      qDebug() << "チャンネルのオープンに失敗";
      return;
    }
    executeCommand();
}
void SSHClient::executeCommand()
{
    int rc = 0;
    do {
      rc = libssh2_channel_exec(m_Channel, "ls -la");
    } while (rc == LIBSSH2_ERROR_EAGAIN);
    if (rc) {
      qDebug() << "lsコマンドの実行に失敗:" << rc;
      return;
    }
    // lsコマンドの出力結果を取得を開始
    QTimer::singleShot(0, this, &SSHClient::readOutput);
}
void SSHClient::onReadyRead()
{
    readOutput();
}
void SSHClient::readOutput()
{
    if (!m_Channel) return;
    QByteArray buffer;
    buffer.resize(1024);
    int rc = 0;
    while (rc != LIBSSH2_ERROR_EAGAIN) {
      rc = libssh2_channel_read(m_Channel, buffer.data(), buffer.size());
      if (rc > 0) {
          qDebug().noquote() << QString::fromUtf8(buffer.constData(), rc);
      }
      else if (rc < 0) {
          qDebug() << "チャンネルの読み取りエラー:" << rc;
          closeChannel();
          return;
      }
    }
    // チャンネルがEOFかどうかを確認
    if (libssh2_channel_eof(m_Channel) == 1) {
      closeChannel();
    }
    else {
      // 続きを読み込む
      QTimer::singleShot(0, this, &SSHClient::readOutput);
    }
}
void SSHClient::closeChannel()
{
    if (!m_Channel) return;
    int rc = 0;
    do {
      rc = libssh2_channel_close(m_Channel);
    } while (rc == LIBSSH2_ERROR_EAGAIN);
    if (rc == 0) {
      int exitcode    = libssh2_channel_get_exit_status(m_Channel);
      char *exitsignal = nullptr;
      libssh2_channel_get_exit_signal(m_Channel, &exitsignal, nullptr, nullptr, nullptr, nullptr, nullptr);
      if (exitsignal) {
          qDebug() << "Exit signal:" << exitsignal;
      }
      else {
          qDebug() << "Exit code:" << exitcode;
      }
    }
    libssh2_channel_free(m_Channel);
    m_Channel = nullptr;
    // Disconnect from the host
    m_Socket->disconnectFromHost();
}
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// main.cppファイル
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // パスワード認証を行う場合
    //SSHClient client("<リモートPC側のIPアドレスまたはホスト名>", <リモートPCのポート番号>,
    //                "<リモートPC側のユーザ名>", "<リモートPC側のユーザパスワード>");
    // 公開鍵認証を行う場合
    SSHClient client("<リモートPC側のIPアドレスまたはホスト名>", <リモートPCのポート番号>,
                    "<リモートPC側のユーザ名>",
                    "<公開鍵ファイルのパス>",  // クライアントPCに秘密鍵があり、リモートPC側に公開鍵が設置されている場合は空欄 ("") にする
                    "<秘密鍵ファイルのパス>",
                    "<秘密鍵のパスフレーズ>");
    client.connectToHost();
    return a.exec();
}
</syntaxhighlight>
<br><br>
== SCPコマンドの使用例 ==
libSSHライブラリおよびlibSSH2ライブラリを使用したSCPコマンドの使用例は、以下に示すページに記載している。<br>
* [[Qtの基礎_-_SCP#libSSHライブラリを使用したSCPコマンドの使用例|libSSHライブラリを使用したSCPコマンドの使用例]]
* [[Qtの基礎_-_SCP#libSSH2ライブラリを使用したSCPコマンドの使用例|libSSH2ライブラリを使用したSCPコマンドの使用例]]
<br><br>
== sshdコマンドの使用 ==
==== OpenSSHのソースコードのダウンロード ====
[https://www.openssh.com/portable.html OpenSSHの公式Webサイト]にアクセスして、ソースコードをダウンロードする。<br>
ダウンロードしたファイルを解凍する。<br>
tar xf openssh-<バージョン>.tar.gz
<br>
このディレクトリ内に必要なヘッダファイル等が存在する。<br>
<br>
なお、OpenSSHのライセンスの全てのコンポーネントは、BSDライセンス、もしくはそれよりも自由なライセンスに属している。<br>
<br>
==== sshd -tコマンド ====
以下の例では、openSSHライブラリを使用して、<code>sshd -t</code>コマンドと同様、指定された設定ファイルの解析と妥当性を確認している。<br>
<br>
# <code>initialize_server_options</code>関数を呼び出して、サーバオプションを初期化する。
# コマンドライン引数からSSHの設定ファイルのパスを取得する。<br>引数が指定されていない場合は、デフォルトの"sshd_config"ファイルを使用する。
# <code>parse_server_config_depth</code>関数を呼び出して、指定されたSSHの設定ファイルを解析する。<br>解析に成功した場合は<code>0</code>、失敗した場合は<code>0以外</code>の値を返す。
# <code>validate_server_config</code>関数を呼び出して、解析された設定ファイルの妥当性を確認する。<br>確認に成功した場合は<code>0</code>、失敗した場合は<code>0以外</code>の値を返す。
# SSHの設定ファイルの解析と妥当性の結果に応じて、成功または失敗のメッセージを表示している。
<br>
<syntaxhighlight lang="c++">
#include <QCoreApplication>
#include <QDebug>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sshbuf.h>
#include <sshkey.h>
#include <authfile.h>
#include <auth-options.h>
#include <servconf.h>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ServerOptions options;
    initialize_server_options(&options);
    // コマンドライン引数からSSHの設定ファイルのパスを取得
    QString configFile = "sshd_config";
    if (a.arguments().size() > 1) {
      configFile = a.arguments().at(1);
    }
    // SSHの設定ファイルの解析
    if (parse_server_config_depth(&options, configFile.toUtf8().constData(), NULL, 0) != 0) {
      qDebug() << QString("SSHの設定ファイルのパースに失敗: %1).arg(configFile);
      return -1;
    }
    // SSHの設定ファイルの妥当性を確認
    if (validate_server_config(&options) != 0) {
      qDebug() << QString("SSHの設定ファイルに誤りがあります: %1").arg(configFile);
      return -1;
    }
    qDebug() << QString("SSHの設定ファイル (%1) は正常です).arg(configFile);
    return 0;
}
</syntaxhighlight>
<br>
==== sshd -Tコマンド ====
以下の例では、openSSHライブラリを使用して、<code>sshd -T</code>コマンドと同様、現在の設定オプションの値をダンプ形式で表示している。<br>
<br>
# <code>initialize_server_options</code>関数を呼び出して、サーバオプションを初期化する。
# <code>fill_default_server_options</code>関数を呼び出して、デフォルトのサーバオプションを設定する。
# <code>parse_server_config_depth</code>関数を呼び出して、sshd_configファイルを解析する。<br>解析に成功した場合は<code>0</code>、失敗した場合は<code>0以外</code>の値を返す。
# 解析に成功した場合は、<code>dump_config</code>関数を呼び出して、設定オプションのダンプを表示する。<br>これは、<code>sshd -T</code>コマンドと同様、現在の設定オプションの値を表示する。
<br>
<syntaxhighlight lang="c++">
#include <QCoreApplication>
#include <QDebug>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sshbuf.h>
#include <sshkey.h>
#include <authfile.h>
#include <auth-options.h>
#include <servconf.h>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    // SSHの設定ファイルオプション
    ServerOptions options;
    initialize_server_options(&options);
    fill_default_server_options(&options);
    if (parse_server_config_depth(&options, "sshd_config", NULL, 0) != 0) {
      qDebug() << "sshd_configファイルのパースに失敗";
      return -1;
    }
    qDebug() << "========= Dump of configuration options =========";
    dump_config(&options);
    qDebug() << "================================================";
    return 0;
}
</syntaxhighlight>
<br><br>
{{#seo:
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux
|image=/resources/assets/MochiuLogo_Single_Blue.png
}}


__FORCETOC__
__FORCETOC__
[[カテゴリ:Qt]]
[[カテゴリ:Qt]]