LoginSignup
1
1
この記事誰得? 私しか得しないニッチな技術で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

[C++]Pythonに追いつきたい!2 自作プログラムでSSH接続する

Last updated at Posted at 2024-06-22

この記事の対象読者

 Pythonparamikoモジュールの使われ方を見たとき、「えっ、こんな手軽にSSHが使えるんだ!」と、感じた事はないでしょうか?「C++で、ワンポイントで手軽にSSHを使いたい。」そんなニッチな方向けの記事です。ちなみに、C++でがっつりSSHを使いたい人向けには、libssh2というライブラリが公開されていますので、こちらをお勧めします。
 また、この技法は、

の、SubProcessクラスを使って構築しています。こちらの記事も、よろしければご覧ください。

仕組みは子プロセスのシェルでSSH接続のスクリプトを実行する

 これだけです。

事前準備としてリモートで接続するコンピュータを用意して、鍵認証でログイン出来るようにしておきましょう

 ssh リモートホスト名+Enter、または、ssh ユーザー名@リモートホスト名+Enterでログイン出来るようにしておきましょう。

コンソール.画面

Microsoft Windows [Version 10.0.19045.4529]
(c) Microsoft Corporation. All rights reserved.

C:\Users\usera>

 このような画面からssh リモートホスト名(または、IPアドレス)を入力すると、

コンソール.画面
Microsoft Windows [Version 10.0.22631.3737]
(c) Microsoft Corporation. All rights reserved.

usera@R5600 C:\Users\usera>

と、リモートホストに、繋がればOKです。

デモコードとスクリプト

この記事で使うソースコードへのリンク

GitHubへのリンクはここです。Visual Studio 2022用に設定されたslnファイルもあります。
  TestProjectをスタートアッププロジェクトに設定し、ソリューションエクスプローラーからtest3.cppを選択し、プロパティの設定で全般->ビルドから除外項目をいいえに設定し、test3.cpp以外はいに設定し、ターゲットCPUをx64に設定し、F5を押下すると実行できます。
image.png

 ソースコードの中にはデバッグ用のライブラリも含んでいます。本質ではない為、今回は説明を割愛いたします。

 この記事で紹介しているソースコードは、公開した時点から変更を加えている事があります。そのため、元の記事とは異なる結果を得る場合があります。また、ソースコードを機能別にディレクトリを分ける等の、改善を行う可能性があります。

デモコード

 下記にデモコードを記載します。その後、番号のコメントが付けられているところの、解説を順次していきます。

test3.cpp
// test3.cpp
#include "test2.h"
using namespace std;

int main() {
	{
		string str;										// 1
		SubProcess sp;
		if (!sp.Popen(R"(cmd.exe /c RemoteCmd.bat)"))
			return 1;

		sp.SleepEx(2000);								// 2
		
		for (; sp.IsActive();) {					// 3
			if (sp.IsReadable()) {
				if (!(sp >> cout))
					return 1;
				else
					sp.SleepEx(10);
					continue;

			} else {
				if (!(sp << cin))
					return 1;
				sp.SleepEx(10);
			}
		}

		if (!(sp.WaitForTermination(INFINITE)))// 4
			return 1;

		DWORD dw = sp.GetExitCodeSubProcess();	// 5
		cout << "\nExit code is " << dw << endl;

		sp.Pclose();									// 6
	}
	_CrtDumpMemoryLeaks();

}

1、cmd.exeを子プロセスとして起動

test3.cpp
		string str;										// 1
		SubProcess sp;
		if (!sp.Popen(R"(cmd.exe /c RemoteCmd.bat)"))
			return 1;

 子プロセスとしてcmd.exeを起動と共に、バッチファイルのRemoteCmd.batを実行。バッチファイルの中身は下記のようになっています。

RemoteCmd.bat
@ssh 192.168.100.205 "cmd.exe" 

 リモートホスト名は、それぞれ自分の環境に、合ったものに書き換えて下さい。

 リモートコンピュータでcmd.exeを起動するようにしています。

2、sp.SleepEx(2000)で、リモートホストの接続完了待ち

test3.cpp
		sp.SleepEx(2000);								// 2

 sp.SleepEx(2000)で最大2秒待ちます。それまでに、リモートコンピュータからデータが送られてきたら、それで待ちは終了です。
 接続に成功すると、例えば次のように表示されます。

ssh接続済み.コンソール
Microsoft Windows [Version 10.0.22631.3737]
(c) Microsoft Corporation. All rights reserved.

usera@R5600 C:\Users\usera>

3、送信と受信を繰り返す

test3.cpp
		for (; sp.IsActive();) {					// 3
			if (sp.IsReadable()) {
				if (!(sp >> cout))
					return 1;
				else
					sp.SleepEx(10);
					continue;

			} else {
				if (!(sp << cin))
					return 1;
				sp.SleepEx(10);
			}
		}

 ここで、送信と受信を繰り返します。chcpコマンドを入力してみましょう。

ssh接続済み.コンソール
usera@R5600 C:\Users\usera>chcp
chcp
݂̃R[h y[W: 932

usera@R5600 C:\Users\usera>

 文字化けしていますね・・・。では次に、exitと入力してみましょう。ssh接続が切断されます。

4、切断された後、ローカルのcmd.exeが終了するのを待つ

text3.cpp
		if (!(sp.WaitForTermination(INFINITE)))// 4
			return 1;

 子プロセスが終了する前に、親プロセスが終了してしまわないようにします。このプロセスを踏んでおかないと、異常終了となる可能性があります。
 このオペレーションが成功すると、

ssh接続済み.コンソール
usera@R5600 C:\Users\usera>exit
exit

といった表示が出ます。

5、exitコードを取得する

test3.cpp
		DWORD dw = sp.GetExitCodeSubProcess();	// 5
		cout << "\nExit code is " << dw << endl;

 exitコードを取得し、表示します。

ssh切断後.コンソール
Exit code is 0

 と、表示されます。

6、子プロセス操作ハンドルを閉じる

test3.cpp
		sp.Pclose();									// 6

 これを実行した後は、exitコードは取得できなくなります。この後、SubProcessクラスは別の子プロセスを立ち上げる事が出来ます。

以上で、デモコードの説明終了です

 いかがでしたでしょうか。

終わりに

 「[C++]Pythonに追いつきたい!2 自作プログラムでSSH接続する」の解説は以上となります。この記事が皆様の閃きや発想のきっかけになりましたら幸いです。
 また、ご意見、ご感想、ご質問など、お待ちしております。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1