2016-12-08 49 views
0

バッチファイルのセットをパラレルで1つのバッチファイルから実行し、それぞれから終了コードを取得する方法を教えてください。私はstartを使用すると、バッチファイルを並列(新しいcmdウィンドウ)で実行しますが、それぞれから終了コードを返しません。コールを使用している間は、終了コードを取得できますが、バッチファイルの実行は順次発生します。私は、次のコードを持っている:これは、並行して別の変数でexec_pmcmd_ctrm.batを3回実行並列でバッチファイルを実行し、それぞれから終了コードを取得

ECHO ON 
setlocal EnableDelayedExpansion 
sqlcmd -S server_name -E -i select_code.sql >\path\output.txt 

for /f "skip=2 tokens=1-3 delims= " %%a in ('findstr /v /c:"-" \path\output.txt') do (

echo $$src=%%a>\path1\%%c.prm 
echo $$trg=%%b>>\path1\%%c.prm 
set param_name=%%c 

start cmd \k \path\exec_pmcmd_ctrm.bat workflow_name %%param_name%% 
ping 1.1.1.1 -n 1 -w 5000 > nul 
set exitcode="%V_EXITCODE%" 
echo %exitcode%>>\path\exitcode.txt 
) 

を、私は、各実行から終了コードを取得することができません。私はコールを使用しようとしたが、その後、私はバットファイルの並列実行が欠場しています。この点に関する助け?

+0

終了コードを収集する別の方法が必要です。 startを使用してプログラムを非同期に実行すると、終了コードを受け取る単一のポイントはありません。私は、Frank P. WestlakeがNamedPipes/MailSlotsで書いたツールを覚えている。それは無料でしたが、まだダウンロード可能かどうかわかりません。 [msdn:Mailslotsについて](https://msdn.microsoft.com/de-de/library/windows/desktop/aa365130(v = vs.85).aspx) – LotPings

+0

「%V_EXITCODE%」はどこでしたか? –

答えて

2

最初に、exit /B valueコマンドで終了する別のバッチファイルの「終了コード」は、%ERRORLEVEL%変数(%V_EXITCODE%ではない)によって取得されます。また、そのような値がのループに変更した場合は、!ERRORLEVEL!(およびプログラムの開始時にEnableDelayedExpansion)の代わりにDelayed Expansionを使用する必要があります。 STARTコマンドは(/ WAITスイッチなし)を使用した場合、ここで誤解があるのでしかし、これらの点で問題が解決しない...

並列 cmd.exeのプロセスが実行を開始します。これは、直接方法がないことを意味します。最初のバッチファイルは、その時点でERRORLEVELを取得するために並列バッチが終了する瞬間を知ることができます。 「開始されたバッチファイルを待つ」コマンドはありませんが、たとえ存在するとしても、複数のバッチファイルが存在するという問題は解決しません。言い換えると、あなたの問題は直接コマンドでは解決できないため、回避する必要があります。

最も簡単な解決策は、パラレルバッチファイルがERRORLEVEL値をファイルに保存し、後で元のバッチファイルで読み取ることができる点です。これは、同じファイルへの同時書き込みアクセスを避けるために同期の問題を意味しますが、それは別の話です...

+1

各バッチファイルを別のファイル(コマンドラインパラメータとして提供可能)に書き込み、すべての実行が終了したらデータを収集することで、同期の問題を回避できます。 – Richard

0

ここでは純粋なソリューションです。基本的に、このスクリプトは、同じディレクトリにあるすべてのバッチファイルを同時に実行します。各バッチファイル(ErrorLevel)は個々のログファイル(バッチファイルと同じ名前で拡張子.log)に書き込まれます。これらのファイルの存在が確認されます。そのようなログファイルが見つかるとすぐに、保存されている終了コードが読み込まれ、それぞれのバッチファイル名とともに概要ログファイルにコピーされます。すべてのログファイルが処理されるとすぐに、このスクリプトは終了します。だからここにコードがある - すべての説明rem発言を参照してください。

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Collect available scripts in an array: 
set /A "INDEX=0" 
for %%J in ("%~dp0*.bat" "%~dp0*.cmd") do (
    if /I not "%%~nxJ"=="%~nx0" (
     set "ITEM=%%~fJ" 
     call set "$BATCH[%%INDEX%%]=%%ITEM%%" 
     set /A "INDEX+=1" 
    ) 
) 

rem // Execute scripts simultaneously, write exit codes to individual log files: 
for /F "tokens=1,* delims==" %%I in ('set $BATCH[') do (
    start "" /MIN cmd /C rem/ ^& "%%~fJ" ^& ^> "%%~dpnJ.log" call echo ^^%%ErrorLevel^^%% 
) 

rem // Deplete summary log file: 
> "%~dpn0.log" rem/ 

rem // Polling loop to check whether individual log files are available: 
:POLLING 
rem // Give processor some idle time: 
> nul timeout /T 1 /NOBREAK 
rem /* Loop through all available array elements; for every accomplished script, 
rem so its log file is availabe, the related array element becomes deleted, 
rem so finally, there should not be any more array elements defined: */ 
for /F "tokens=1,* delims==" %%I in ('set $BATCH[') do (
    rem // Suppress error message in case log file is not yet available: 
    2> nul (
     rem // Read exid code from log file: 
     set "ERRLEV=" & set "FILE=" 
     < "%%~dpnJ.log" set /P ERRLEV="" 
     if defined ERRLEV (
      rem // Copd the read exit code to the summary log file: 
      set "NAME=%%~nxJ" 
      >> "%~dpn0.log" call echo(%%ERRLEV%% "%%NAME%%" 
      rem // Undefine related array element: 
      set "%%I=" 
      rem // Store log file path for later deletion: 
      set "FILE=%%~dpnJ.log" 
     ) 
     rem // Delete individual log file finally: 
     if defined FILE call del "%%FILE%%" 
    ) 
) 
rem // Jump to polling loop in case there are still array elements: 
> nul 2>&1 set $BATCH[ && goto :POLLING 

endlocal 
exit /B 

このアプローチを私は、次のImproving Batch File for loop with start subcommandで使用されるものと非常によく似ていますが、同時に実行されたコマンドの存在出力が収集されます。

+0

ありがとう@aschipfl ..上記のスクリプトに基づいて動作させました。私はtxtファイルにいくつかのパラメータを集め、行ごとにストアドプロシージャに渡す必要があります。以下のコードを試してみてください:tokens = 1-3 delims =、 "%% a in( '\ path \ batch_output.txt')do( sqlcmd -S servername -E -i path \ spu_update_src_trg_ref.sql -v %% a、%% b、%% c) 'しかし、 'do('はここでは予期せぬエラー)を受け取っています – Anurag

+0

' do' + _space_ + '(' ... – aschipfl

関連する問題