はじめに
複数のCachéサーバを管理する場合、Cachéサーバ間で任意のコードを実行するタスクが発生する場合があります。 さらに、システム管理者のニーズなどのために、リモートCachéサーバで任意のコードを実行する必要がある場合があります。これらの問題を解決するために、 RCEユーティリティが開発されました。
そのような問題を解決するためのオプションは何ですか?また、RCE(リモートコード実行)は何を提供しますか?
すでに何がありますか?
»ローカルOSコマンド
簡単なものから始めましょう-Cachéからローカルオペレーティングシステムコマンドを実行します。 これには関数$ zfが使用されます。
- $ ZF(-1) -オペレーティングシステムのプログラムまたはコマンドを呼び出します。 呼び出しは新しいプロセスで実行され、親プロセスは呼び出されたプロセスの完了を待っています。 実行後、$ ZF(-1)はプロセスのステータスを返します。実行が成功した場合は0、エラーが発生した場合は1、プロセスの作成に失敗した場合は-1。
次のようになります。set status = $ ZF (-1、 "mkdir" "test folder" "" )
- $ ZF(-2) -同様ですが、メインプロセスは作成されたプロセスの結果を待機しません。 その結果、プロセスの作成が成功した場合は0が返され、プロセスの作成が失敗した場合は-1が返されます。
%Net.Remote.Utilityクラスのメソッドを使用することもできます。これは、標準関数の便利なラッパーを提供します。その利点は、呼び出されたプロセスの出力がより便利な形式になっていることです。
- RunCommandViaCPIPE- コマンドパイプを介してコマンドを実行します。 作成されたデバイスとプロセスの出力を含む文字列を返します。 コマンドパイプを使用したサーバーでのコマンドの直接実行については、この記事の Habréで説明しています 。
- RunCommandViaZF-$ ZF(-1)を介してコマンドを実行します。 プロセスの出力をファイルに書き込み、文字列として返します。
別の方法は、端末コマンドを使用することです! (または$、これらは同一)、Cachéターミナル内でオペレーティングシステムのシェルを開きます。 操作には2つのモードがあります。
- 単一行-で! チーム自体が転送されます。 シェルインタープリタによって直ちに実行され、その出力は現在のCachéデバイスに送信されます。 前の例は次のようになります。
SAMPLES>! mkdir ""test folder""
- 複数行-最初に実行されます!これにより、ユーザーが既にオペレーティングシステムコマンドを入力しているシェルが開かれます。 終了は、(シェルに応じて)quitまたはexitを使用して実行されます。
SAMPLES>! C:\InterSystems\Cache\mgr\samples\> mkdir "test folder" C:\InterSystems\Cache\mgr\samples\> quit SAMPLES>
»COSコードのリモート実行
おそらく、次の機能が利用可能な%Net.RemoteConnectionクラスを使用します。
- 格納されたオブジェクトを開いて変更します。
- クラスおよびオブジェクトメソッドの実行。
- リクエストの履行。
これらの機能を示すサンプルコード
rc = ##クラス ( %Net.RemoteConnection )を設定します。 %新規 ()
Status = rcに 設定し ます。 Connect ( "127.0.0.1" 、 "SAMPLES" 、1972、 "_system" 、 "SYS" ) break : ' ステータス
Status = rcに 設定し ます。 OpenObjectId ( " Sample.Person " 、1、 。per ) break : ' ステータス
Status = rcに 設定し ます。 GetProperty ( per 、 "Name" 、。Value ) break : ' ステータス
値 を書き込む
Status = rcに 設定し ます。 ResetArguments () break : ' ステータス
Status = rcに 設定し ます。 SetProperty ( per 、 "Name" 、 "Jones、Tom" _ $ r (100)、4) break : ' ステータス
Status = rcに 設定し ます。 ResetArguments () break : ' ステータス
Status = rcに 設定し ます。 GetProperty ( per 、 "Name" 、。Value ) break : ' ステータス
値 を書き込む
Status = rcに 設定し ます。 ResetArguments () break : ' ステータス
Status = rcに 設定し ます。 AddArgument (150.0) break : ' ステータス //加算150 + 10
Status = rcに 設定し ます。 AddArgument (10,0) break : ' ステータス //加算150 + 10
Status = rcに 設定し ます。 InvokeInstanceMethod ( per 、 "Addition" 、。 AdditionValue 、1) break : ' ステータス
AdditionValue を書き込む
Status = rcに 設定し ます。 ResetArguments () break : ' ステータス
Status = rcに 設定し ます。 InstantiateQuery ( 。Rs 、 "Sample.Person" 、 "ByName" )
Status = rcに 設定し ます。 Connect ( "127.0.0.1" 、 "SAMPLES" 、1972、 "_system" 、 "SYS" ) break : ' ステータス
Status = rcに 設定し ます。 OpenObjectId ( " Sample.Person " 、1、 。per ) break : ' ステータス
Status = rcに 設定し ます。 GetProperty ( per 、 "Name" 、。Value ) break : ' ステータス
値 を書き込む
Status = rcに 設定し ます。 ResetArguments () break : ' ステータス
Status = rcに 設定し ます。 SetProperty ( per 、 "Name" 、 "Jones、Tom" _ $ r (100)、4) break : ' ステータス
Status = rcに 設定し ます。 ResetArguments () break : ' ステータス
Status = rcに 設定し ます。 GetProperty ( per 、 "Name" 、。Value ) break : ' ステータス
値 を書き込む
Status = rcに 設定し ます。 ResetArguments () break : ' ステータス
Status = rcに 設定し ます。 AddArgument (150.0) break : ' ステータス //加算150 + 10
Status = rcに 設定し ます。 AddArgument (10,0) break : ' ステータス //加算150 + 10
Status = rcに 設定し ます。 InvokeInstanceMethod ( per 、 "Addition" 、。 AdditionValue 、1) break : ' ステータス
AdditionValue を書き込む
Status = rcに 設定し ます。 ResetArguments () break : ' ステータス
Status = rcに 設定し ます。 InstantiateQuery ( 。Rs 、 "Sample.Person" 、 "ByName" )
このコードでは次が発生します。
- Cachéサーバーへの接続。
- Id 1でSample.Personクラスのインスタンスを開きます。
- プロパティ値の取得。
- プロパティの値を変更します。
- メソッドの引数を設定します。
- インスタンスメソッドを呼び出します。
- リクエストSample.Personの履行:ByName 。
%Net.RemoteConnectionが要求を送信するサーバー側で機能するには、 C ++バインディングを構成する必要があります。
それとは別に、Habréで記述されたECPテクノロジーに言及する必要があります。これにより、データベースサーバー上のアプリケーションサーバーからリモートJOBプロセスを呼び出すことができます。
その結果、上記で提案した2つのアプローチを組み合わせることで、原則として、この記事の冒頭で設定した目標を達成することができますが、既存のアプローチを使用する場合は難しいと思われる、ユーザーが新しい実行可能スクリプトを作成する簡単なプロセスを達成したいと考えました。
Rce
したがって、プロジェクトには次の目標がありました。
- Cachéからのリモートサーバーでのスクリプト作成。
- リモートサーバー(以下、クライアントと呼びます)を構成する必要はありません。
- ローカルサーバー(以下、サーバーと呼びます)の最小限の構成。
- オペレーティングシステムとCOSコマンド間のユーザーフレンドリーな切り替え。
- クライアントとしてのWindowsおよびLinuxのサポート。
プロジェクトのクラス階層は次のとおりです。
階層マシン-OS-インスタンスは、リモートサーバーへのアクセスに必要な情報を格納するために使用されます。
コマンドを保存するには、RCE.Scriptクラスを使用します。このクラスには、OSコマンドまたはCOSコードのいずれかであるRCE.Commandクラスのオブジェクトのシーケンシャルリストが含まれています。
コマンド例:
ommand1 = ## class ( RCE.Command )を設定します。 %新規 ( "cd 1" 、0)
ommand2 = ## class ( RCE.Command )を設定します。 %新規 ( "zn" "%SYS" "" 、1)
最初の引数はコマンドのテキスト、2番目は実行レベルです:0-OS、1-キャッシュ。
新しいスクリプトを作成する例:
Set Script = ## class ( RCE.Script )。 %新規 ()
スクリプトを実行し ます。 挿入 ( ##クラス ( RCE.Command )。 %新規 ( "touch 123" 、0))
スクリプトを実行し ます。 挿入 ( ## class ( RCE.Command )。 %New ( "set ^ test = 1" 、1))
スクリプトを実行し ます。 挿入 ( ## class ( RCE.Command )。 %New ( "set ^ test(1)= 2" 、1))
スクリプトを実行し ます。 挿入 ( ##クラス ( RCE.Command )。 %新規 ( "touch 1234" 、0))
スクリプトを実行し ます。 %保存 ()
この場合、OSレベルでは、Cachéで1番目と4番目のコマンドが実行され、2番目と3番目のコマンドが実行され、実行レベルを切り替えるプロセスはユーザーに対して完全に透過的です。
»実行メカニズム
次の実行パスがサポートされるようになりました。
サーバー
| お客様 |
---|---|
Linux
| Linux、Windows(クライアントにSSHサーバーをインストールする必要があります)
|
窓
| Linux、Windows(クライアントにSSHサーバーをインストールするか、サーバーにpsexecをインストールする必要があります)
|
サーバーとクライアントの両方がWindowsを実行している場合、batファイルが生成され、クライアントに送信され、psexecユーティリティを使用して実行されます。
»サーバーの追加
リポジトリから任意のスコープにクラスをダウンロードします 。 Windowsサーバーがあり、他のWindowsサーバーを管理する場合は、psexecユーティリティへのパスに等しいグローバル値^設定( "exec")を設定します。 これでセットアップは完了です!
»クライアントを追加する
認証に必要なすべてのデータを保存することにあります。
新しい階層を作成するコード例マシン-OS-インスタンス
Machine = ## class ( RCE.Machine )を設定します。 %新規 ()
マシンを 設定し ます。 IP = 「IPまたはホスト」
OS = ##クラス ( RCE.OS )を設定します。 %New ( "OS" ) // LinuxまたはWindows
OSを 設定し ます 。 ユーザー名 = "OSユーザー名"
OSを 設定し ます 。 パスワード = 「ユーザーパスワード」
インスタンスの 設定 = ##クラス ( RCE.Instance )。 %新規 ()
インスタンスを 設定し ます。 名前 = 「Cachéインスタンス名」
インスタンスを 設定し ます。 User = "Cachéusername" //最小のセキュリティ設定が設定されている場合は不要
インスタンスを 設定し ます。 Pass = "CachéUser Password" //最小のセキュリティ設定が設定されている場合は不要
インスタンスを 設定し ます。 Dir = "インスタンスctermへのパス" // ctermがPATHにない場合にのみ必要(Windowsクライアントの場合)
インスタンスを 設定し ます。 OS = OS
OSを 設定し ます 。 マシン = マシン
$ System .Status を書き込み ます。 GetErrorText ( Machine 。 %Save ())
マシンを 設定し ます。 IP = 「IPまたはホスト」
OS = ##クラス ( RCE.OS )を設定します。 %New ( "OS" ) // LinuxまたはWindows
OSを 設定し ます 。 ユーザー名 = "OSユーザー名"
OSを 設定し ます 。 パスワード = 「ユーザーパスワード」
インスタンスの 設定 = ##クラス ( RCE.Instance )。 %新規 ()
インスタンスを 設定し ます。 名前 = 「Cachéインスタンス名」
インスタンスを 設定し ます。 User = "Cachéusername" //最小のセキュリティ設定が設定されている場合は不要
インスタンスを 設定し ます。 Pass = "CachéUser Password" //最小のセキュリティ設定が設定されている場合は不要
インスタンスを 設定し ます。 Dir = "インスタンスctermへのパス" // ctermがPATHにない場合にのみ必要(Windowsクライアントの場合)
インスタンスを 設定し ます。 OS = OS
OSを 設定し ます 。 マシン = マシン
$ System .Status を書き込み ます。 GetErrorText ( Machine 。 %Save ())
»スクリプトの実行
前の例を続けると、スクリプトの実行は非常に簡単です-スクリプトオブジェクトと実行領域が転送されるRCE.InstanceクラスのExecuteScriptメソッドを使用して(デフォルトでは-%SYS):
ステータス = インスタンスを 設定し ます。 ExecuteScript ( スクリプト 、 "USER" )
結論
RCEは、InterSystemsCachéからのリモートコード実行に便利なメカニズムを提供します。 スクリプトは保存されるため、スクリプトを1回だけ記述するだけで、いつでも任意の数のクライアントで実行できます。
参照資料
GitHub RCEリポジトリ
RCEプロジェクトクラスアーカイブ