[C++]Pythonに追いつきたい!2 自作プログラムでSSH接続する
この記事の対象読者
Pythonのparamikoモジュールの使われ方を見たとき、「えっ、こんな手軽に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
を押下すると実行できます。
ソースコードの中にはデバッグ用のライブラリも含んでいます。本質ではない為、今回は説明を割愛いたします。
この記事で紹介しているソースコードは、公開した時点から変更を加えている事があります。そのため、元の記事とは異なる結果を得る場合があります。また、ソースコードを機能別にディレクトリを分ける等の、改善を行う可能性があります。
デモコード
下記にデモコードを記載します。その後、番号のコメントが付けられているところの、解説を順次していきます。
// 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を子プロセスとして起動
string str; // 1
SubProcess sp;
if (!sp.Popen(R"(cmd.exe /c RemoteCmd.bat)"))
return 1;
子プロセスとしてcmd.exe
を起動と共に、バッチファイルのRemoteCmd.bat
を実行。バッチファイルの中身は下記のようになっています。
@ssh 192.168.100.205 "cmd.exe"
注意
リモートホスト名は、それぞれ自分の環境に、合ったものに書き換えて下さい。
リモートコンピュータでcmd.exe
を起動するようにしています。
sp.SleepEx(2000)
で、リモートホストの接続完了待ち
2、 sp.SleepEx(2000);// 2
sp.SleepEx(2000)
で最大2秒待ちます。それまでに、リモートコンピュータからデータが送られてきたら、それで待ちは終了です。
接続に成功すると、例えば次のように表示されます。
Microsoft Windows [Version 10.0.22631.3737]
(c) Microsoft Corporation. All rights reserved.
usera@R5600 C:\Users\usera>
3、送信と受信を繰り返す
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
コマンドを入力してみましょう。
usera@R5600 C:\Users\usera>chcp
chcp
݂̃R[h y[W: 932
usera@R5600 C:\Users\usera>
文字化けしていますね・・・。では次に、exit
と入力してみましょう。ssh接続が切断されます。
4、切断された後、ローカルのcmd.exeが終了するのを待つ
if (!(sp.WaitForTermination(INFINITE)))// 4
return 1;
子プロセスが終了する前に、親プロセスが終了してしまわないようにします。このプロセスを踏んでおかないと、異常終了となる可能性があります。
このオペレーションが成功すると、
usera@R5600 C:\Users\usera>exit
exit
といった表示が出ます。
5、exitコードを取得する
DWORD dw = sp.GetExitCodeSubProcess(); // 5
cout << "\nExit code is " << dw << endl;
exitコードを取得し、表示します。
Exit code is 0
と、表示されます。
6、子プロセス操作ハンドルを閉じる
sp.Pclose();// 6
これを実行した後は、exitコードは取得できなくなります。この後、SubProcessクラスは別の子プロセスを立ち上げる事が出来ます。
以上で、デモコードの説明終了です
いかがでしたでしょうか。
終わりに
「[C++]Pythonに追いつきたい!2 自作プログラムでSSH接続する」の解説は以上となります。この記事が皆様の閃きや発想のきっかけになりましたら幸いです。
また、ご意見、ご感想、ご質問など、お待ちしております。
Discussion