前のトピック: batch次のトピック: コマンド


パイプ

パイプ インターフェースは、バッチ処理とコマンド直接呼び出しの双方の利点を兼ね備えています。つまり、バッチ オプションと同様に CLI とマネージャ間の 1 回のセッションで複数のコマンドを実行することができます。またその一方で、スクリプトはそのコマンドの出力結果を次の CLI コマンドを開始する前に処理することが可能です。 パイプ インターフェースを起動するには、パイプ キーワードに続けて、CLI がリスニングするパイプの名前を指定します。 指定するパイプは、Windows では名前付きパイプ、Linux では fifo ファイルです。 どちらの場合も、CLI はパイプ クライアントとして機能します。つまり、呼び出し元のスクリプトでパイプを作成および管理する必要があります。 CLI は、パイプ インターフェースを処理するために呼び出されると、クレデンシャルが入力された指定のマネージャへの接続を確立し、その結果を stdout に記録します。 セッションが確立されると、何らかのコマンドの処理に備え、CLI によるパイプのリスニングが行われます。 コマンドを受け取ると、そのコマンドを処理し、結果を stdout に記録します。 処理が終わると、再び次のコマンドに対するリスニングを開始します。 パイプ モードの CLI は、バッチ モードと異なり、コマンドが正常に処理されたかどうかに関係なく、常にパイプに制御を戻します。コマンドが失敗した場合でも、CLI とマネージャ間のセッションが終了することはありません。 この動作は、バッチ モードで CADSMCMD_CONTINUE=ON を指定した場合に相当します。

CLI と起動スクリプト間の通信および同期を円滑にするため、CLI には CLI 処理が終了し、CLI が再びパイプのリスニングを開始したことを示すアイ キャッチャがいくつか用意されています。

パイプ モードの CLI を起動すると、CLI が stdout に以下のメッセージを出力します。

*** SDCMD: Line up ***

マネージャへのセッションが確立され、CLI がパイプのリスニングを開始します。 この時点で、スクリプトがパイプ経由で CLI にコマンドを送信できるようになります。 コマンド処理の終了も、特殊なアイ キャッチャによってレポートされます。 コマンドが終了すると、正常に終了したかどうかに関係なく、常に CLI が stdout に以下のメッセージを出力します。

### SDCMD: -eoc ###

スクリプトは、この文字列を検出すると、自身の起動したコマンドが終了し、コマンド出力がすべて stdout に書き込まれたことを認識します。

アプリケーションからパイプ経由で送信されるコマンドは、バッチ ファイルと同じ形式のものになります。 アプリケーションによってパイプに書き込まれるコマンド バッファには、実行対象のコマンドが完全な形で存在している必要があります。 1 つのコマンドを複数の送信バッファに配信することはできません。

これに対して、複数のコマンドを 1 つのバッファに送信することは可能です。 この場合、送信する各コマンドは以下の文字列で区切られている必要があります。

-eoc

CLI が以下の文字列をパイプ経由で受け取ると、

-quit

ただちにパイプ モードの CLI とマネージャ間のセッションが終了します。

「pipe」キーワードに続けて、CLI が処理対象のコマンドを受け取るために使用するパイプの名前(pipename)をコーディングすると、CLI がパイプ インターフェースに対して呼び出されます。 キーワードとパイプ名との間には、1 つ以上の空白が必要です。

以下の例は、Linux でのパイプ インターフェースの使用法を示したものです。 このスクリプトを実行すると、USD に登録されているターゲット コンピュータおよび USD ソフトウェア ライブラリに登録されている製品が一覧表示されます。

#! /usr/bin/sh
proto ()
{
	aa=" "
	bb=`echo "$aa" | grep "SDCMD: Line up"`
	while [ -z "$bb" ]
	do
		read aa
		bb=`echo "$aa" | grep "SDCMD: Line up"`
		if [ -z "$bb" ]
		then
			echo "$aa"
		fi
	done
}
prot ()
{
	aa=" "
	bb=`echo "$aa" | grep "SDCMD: -eoc"`
	while [ -z "$bb" ]
	do
		read aa
		bb=`echo "$aa" | grep "SDCMD: -eoc"`
		if [ -z "$bb" ]
		then
			echo "$aa"
		fi
	done
}

mkfifo /ca_dsmcmd_in
mkfifo /ca_dsmcmd_out
{
	cadsmcmd pipe /ca_dsmcmd_in > /ca_dsmcmd_out &
	proto
	echo "targetComputer action=list -eoc" > /ca_dsmcmd_in
	prot
	#
	#  store returned list and process it
	#
	#     ...
	#
	#  next command
	echo "swLibrary action=list -eoc" > /ca_dsmcmd_in
	prot
	#
	#  store returned list and process it
	#
	#     ...
	#
	#  terminate session
	echo "-quit" > /ca_dsmcmd_in
} < /ca_dsmcmd_out
rm /ca_dsmcmd_*

この例は、2 つのルーチンとメインライン部で構成されています。 ルーチン「proto ()」はパイプ インターフェースが開始されコマンドの待機中であることを示す「### SDCMD: Line up ###」に対してトリガされ、ルーチン「prot ()」はコマンドの処理が完了したことを示す「### SDCMD: -eoc ###」に対してトリガされます。

メインライン部では、まずパイプが 2 つ作成されます。 パイプ「/ca_dsmcmd_in」は、CLI が入力パイプとして使用するものです。つまり、CLI はこのパイプ経由で処理対象のコマンドを受け取ります。 もう 1 つのパイプ「/ca_dsmcmd_out」は、スクリプトが出力結果を処理できるよう、CLI の stdout をスクリプトにリダイレクトするために使用されます。 この 2 つのパイプが作成された後、パイプ モードの CLI をバッチで起動するブロックが開始され、targetComputer および swLibrary に対してそれぞれ list コマンドが実行されます。これが完了すると、セッションが終了します。 このブロックは、「/ca_dsmcmd_out」パイプから入力を受け取り、CLI の出力を記録します。 「/ca_dsmcmd_out」パイプは、CLI の存続時間中スクリプトのために常に開いたままにしておいてください。 このために、このブロックの入力としてこのパイプが割り当てられているからです。 たとえば、「/ca_dsmcmd_out」パイプを proto ルーチンおよび prot ルーチンへの入力としてのみ割り当てた場合には、実行時にデータの損失を伴う問題が発生し、セッションがハングアップすることがあります。

パイプ モードの CLI がバッチで起動された後、CLI をトリガして機能可能な状態にするため proto ルーチンが使用されます。 スクリプトは制御が戻ると、targetComputer に対するリスト アクションを起動し、prot ルーチンを使用してコマンド処理の終了を判断します。 この prot ルーチンの出力は、後続のスクリプト処理で利用できるよう、ファイルにリダイレクトすることもできます。 次に、swLibrary に対するリスト アクションが起動し、コマンド処理の終了を判断するために再び prot ルーチンが使用されます。 この prot ルーチンの出力も、後続のスクリプト処理で利用できるよう、ファイルにリダイレクトすることができます。 最後に、-quit で CLI をシャットダウンしてこのブロックが終了します。

スクリプトの最終行は、パイプをハウスキーピングおよびクリーン アップするためのものです。

以下の例は、前述の例と同じ作業を実行するものですが、DM Scripting を使用しており、Windows 向けの内容になっています。

Dim hPipeIn, hPipeOut As Integer
Dim pipeIn, pipeOut As String
Dim command_1, command_2, eoc, eop, lineUp, endOfCommand, buffer As String

' ************************************************************************
' clear screen
ClrScr()

' ************************************************************************
' set constants
eoc = " -eoc"
eop = "-quit"
command_1 = "targetComputer action=list" + eoc
command_2 = "swLibrary action=list" + eoc
lineUp = "SDCMD: Line up"
endOfCommand = "SDCMD: -eoc"

pipeIn ="¥¥.¥pipe¥ca_dsmcmd_in"
pipeOut ="¥¥.¥pipe¥ca_dsmcmd_out"

' ************************************************************************
' Create input pipe of CLI
hPipeIn = CreatePipe(pipeIn, O_WRITE)
If (hPipeIn = -1) Then
	MsgBox("Open pipe """ + pipeIn + """ failed.", "Pipe test", MB_OK + 					MB_ICONSTOP + MB_SETFOREGROUND)
	exit
EndIf

' ************************************************************************
' Create output pipe of CLI
hPipeOut = CreatePipe(pipeOut, O_READ)
If (hPipeOut = -1) Then
	MsgBox("Open pipe """ + pipeOut + """ failed.", "Pipe test", MB_OK + MB_ICONSTOP + MB_SETFOREGROUND) 
	CloseFile(hPipeIn)
	exit
EndIf

' ************************************************************************
' Launch cadsmcmd in pipe mode using pipeIn as input pipe and redirecting
‘ stdout to pipeOut
Execute("cmd /c ""cadsmcmd pipe " + pipeIn + " > " + pipeOut + """", 					FALSE, 0)
While (TRUE)
	If (Not(ReadFile(hPipeOut, buffer))) Then
		MsgBox("Read from pipe """ + pipeOut + """ failed.", "Pipe test", 					MB_OK + MB_ICONSTOP + MB_SETFOREGROUND)
		CloseFile(hPipeIn)
		CloseFile(hPipeOut)
		exit
	EndIf
	If (InStr(buffer, lineUp) = 0) Then
		Print(buffer)
	Else
		ExitWhile
	EndIf
Wend

' ************************************************************************
' launch request for a targetComputer action=list
If (Not(WriteFile(hPipeIn, command_1))) Then
	MsgBox("Write to pipe """ + pipeIn + """ failed.", "Pipe test", MB_OK + 				MB_ICONSTOP + MB_SETFOREGROUND)
	CloseFile(hPipeIn)
	CloseFile(hPipeOut)
	exit
EndIf
While (TRUE)
	If (Not(ReadFile(hPipeOut, buffer))) Then
		MsgBox("Read from pipe """ + pipeOut + """ failed.", "Pipe test", 					MB_OK + MB_ICONSTOP + MB_SETFOREGROUND)
		CloseFile(hPipeIn)
		CloseFile(hPipeOut)
		exit
	EndIf
	If (InStr(buffer, endOfCommand) = 0) Then
		' results could be stored for subsequent processing or directly processed.
		Print(buffer)
	Else
		ExitWhile
	EndIf
Wend

' ************************************************************************
' launch request for a swLibrary action=list
If (Not(WriteFile(hPipeIn, command_2))) Then
	MsgBox("Write to pipe """ + pipeIn + """ failed.", "Pipe test", MB_OK + 				MB_ICONSTOP + MB_SETFOREGROUND)
	CloseFile(hPipeIn)
	CloseFile(hPipeOut)
	exit
EndIf
While (TRUE)
	If (Not(ReadFile(hPipeOut, buffer))) Then
		MsgBox("Read from pipe """ + pipeOut + """ failed.", "Pipe test", 					MB_OK + MB_ICONSTOP + MB_SETFOREGROUND)
		CloseFile(hPipeIn)
		CloseFile(hPipeOut)
		exit
	EndIf
	If (InStr(buffer, endOfCommand) = 0) Then
		' results could be stored for subsequent processing or directly processed.
		Print(buffer)
	Else
		ExitWhile
	EndIf
Wend

' ************************************************************************
' terminate CLI
If (Not(WriteFile(hPipeIn, eop))) Then
	MsgBox("Write to pipe """ + pipeIn + """ failed.", "Pipe test", MB_OK + 				MB_ICONSTOP + MB_SETFOREGROUND)
	CloseFile(hPipeIn)
	CloseFile(hPipeOut)
	exit
EndIf

' ************************************************************************
' clean up
CloseFile(hPipeIn)
CloseFile(hPipeOut)

CLI の有効なコマンドはすべて、パイプ インターフェースで利用することができます。