1

DCLと並行して実行するいくつかのバックグラウンドプロセスを起動する方法を探しています。それらがすべて完了するのを待って、それらがすべて成功したか、少なくとも1つが失敗したかを知りたいと思います。これは、&を使用してbashで待機するようなものです。

spawn / nowaitのドキュメントを読みましたが、複数のサブプロセスを生成した後に待機する方法がわかりません。サブプロセスが終了するときにファイルに書き込み、スリープループで親からファイルをチェックすることができると思いますか?しかし、より良い/組み込みの方法はありますか?

4

5 に答える 5

4

2つの信頼できる手段は次のとおりです。

submitそれらをバッチジョブとして使用する場合は、コマンドを使用してsynchronizeそれぞれを順番に待機できます。

を使用run/detachしてプロセスを開始すると/mailbox、終了メッセージを受信するように指定できます。

サブプロセスは少し異なります。1つのアプローチは、論理名テーブルを共有し、それに応じて各サブプロセスにステータスを更新させることです。異常終了が報告される保証はありません。

追加の作業を行う場合は、いくつかの小さなアプリケーションを作成して、ロックマネージャーまたは共通のイベントフラグクラスターを使用してステータスの更新を伝達できます。

于 2013-02-05T03:47:33.933 に答える
1
$   BKGVFY = F$VERIFY(0)  !******Start of BACKGROUND******
$!*DOC+
$!*
$!* Procedure    : BACKGROUND.COM
$!*
$!*   Abstract   : Invoke Commands in Background
$!*
$!*   Prototype  : @MYDCL:BACKGROUND "RUN PROG1" "@COMFIL" "RUN PROG2"
$!*
$!*   Description: This utility is used to run background spawned jobs. It
$!*                will return control after all of the jobs have run.
$!*
$!*          Note: Requires GRPNAM or SYSNAM Privilege
$!*
$!* Parameters   : P1 = Background Command (Required)
$!*                P2 = Background Command (Optional)
$!*                P3 = Background Command (Optional)
$!*                P4 = Background Command (Optional)
$!*                P5 = Background Command (Optional)
$!*                P6 = Background Command (Optional)
$!*                P7 = Background Command (Optional)
$!*                P8 = Background Command (Optional)
$!*
$!* Change Control Log:
$!*
$!*        Who         Date      Description
$!*  --------------- ----------  -----------
$!*  Scott Kelbell   02/16/2010  Initial version
$!*
$!*DOC-
$   !
$   ! VALIDATION
$   !
$   IF P1 .EQS. "" .OR. P1 .EQS. "HELP" .OR. P1 .EQS. "?" THEN EXIT
$   IF F$PRIVILEGE("GRPNAM")
$   THEN
$     BKGPRIV = "GROUP"
$   ELSE
$     IF F$PRIVILEGE("SYSNAM")
$     THEN
$       BKGPRIV = "SYSTEM"
$     ELSE
$       WRITE SYS$OUTPUT "%BACKGROUND-F-IPRV, insufficient priv (GRPNAM)"
$       EXIT
$     ENDIF
$   ENDIF
$   !
$   ! INITIALIZATION
$   !
$   BKGN     = "BKG" + F$UNIQUE()   ! Background Logical Prefix
$   BKGFIL   = "SYS$LOGIN:" + BKGN  ! Background File Prefix
$   BKGCNT   = 0                    ! Parameter Counter
$   !
$   ! MAINLINE
$   !
$ LOOP:
$   IF BKGCNT .EQ. 8 THEN GOTO LOOP_WAIT
$   BKGCNT = BKGCNT + 1
$   IF P'BKGCNT' .NES. ""                           ! For each parameter
$   THEN
$     BKGLOG = BKGFIL + ".LOG_" + F$STRING(BKGCNT)
$     CREATE/FDL=NL: 'BKGFIL'.TMP_'BKGCNT' ! Create the command procedure
$     OPEN/APPEND 'BKGN' 'BKGFIL'.TMP_'BKGCNT'
$     BKGLNM = BKGN + "_" + F$STRING(BKGCNT)
$     WRITE 'BKGN' "$ SET VERIFY"
$     WRITE 'BKGN' "$ ! Background Job #", P'BKGCNT', " ", F$TIME()
$     WRITE 'BKGN' "$ SET NOON"
$     WRITE 'BKGN' "$ DEFINE/NOLOG/", BKGPRIV, " ", BKGLNM, " RUNNING"
$     WRITE 'BKGN' "$ ", P'BKGCNT'
$     WRITE 'BKGN' "$ DEFINE/NOLOG/", BKGPRIV, " ", BKGLNM, " FINISHED"
$     WRITE 'BKGN' "$ EXIT ! End of Background Job"
$     CLOSE 'BKGN'
$     DEFINE/'BKGPRIV' 'BKGN'_'BKGCNT' INITIALIZED
$     SPAWN/NOWAIT/OUTPUT='BKGLOG'/NOLOG @'BKGFIL'.TMP_'BKGCNT'
$     GOTO LOOP
$   ENDIF
$   BKGCNT = BKGCNT - 1
$   !
$   ! WAIT LOGIC
$   !
$ LOOP_WAIT:
$   CURLOG = BKGN + "_" + F$STRING(BKGCNT)
$   IF F$TRNLNM("''CURLOG'") .NES. "FINISHED"
$   THEN
$     WAIT 00:00:05
$     GOTO LOOP_WAIT
$   ENDIF
$   DEASSIGN/'BKGPRIV' 'BKGN'_'BKGCNT'
$   DELETE/NOLOG/NOCONFIRM 'BKGFIL'.TMP_'BKGCNT';*
$   BKGCNT = BKGCNT - 1
$   IF BKGCNT .GT. 0 THEN GOTO LOOP_WAIT
$   !
$   ! EXIT LOGIC
$   !
$ EXIT:
$   BKGVFY = F$VERIFY(BKGVFY) !******End of BACKGROUND******
于 2013-02-05T14:04:11.210 に答える
0

指摘したように、SYNCHRONIZEは最も堅牢な方法です。

ずさんな、しかし多くの場合適切な方法の1つは、最初にspawn / nowaitを使用して最短寿命のタスクを作成し、最後に実行されると予想されるタスクをspawn/waitすることです。

これを強化するには、F$CONTEXTでMASTER_PID=your-pidを探してポーリングループに入り、オプションのF$GETJPIを使用して返されたF$PID値の数をカウントします。

ハックな方法は、たとえば、プロセス名を再利用しようとしたり、プロセスが終了した後にのみ機能する共有を許可しないプロセスログファイルを開いたり、SHOW PROC/SUB出力を解析したりすることです。

たぶん、(lib $)spawnの束を実行し、完了ASTを使用してすべてが完了したことを把握するための、単純なシェルプログラムを作成できますか?

CRTL関数waitpidを確認することもできます。

hth、ハイン。

于 2013-02-05T14:21:50.100 に答える
0

あなたはいつでもPerlでパイプオープンを行い、それをwaitpidで待つことができます:

$ perl -e "my $pid = open F, '| wait 00:00:05'; print qq/waiting for $pid\n/; waitpid($pid, 0); close F;"
waiting for 6233

「wait00:00:05」コマンドの代わりに、待機する実際のDCLコマンドを使用します。ここで、ファイルハンドルFは、子のstdin / SYS$INPUTに接続された書き込み専用のファイルハンドルです。子がSYS$INPUTでブロッキング読み取りを行う場合、親は期待するものを何でも書き込む必要があります。そうしないと、子はハングします。または、パイプ文字を配置することもできます| コマンドの最後でFは、子のstdout / SYS$OUTPUTに接続された読み取り専用のファイルハンドルになります。複数の子を待機している場合は、waitpid()ではなくwait()を使用する必要がある場合があります。

于 2013-02-06T15:50:43.343 に答える
0

suprocessカウントをポーリングするだけです。f $ getjpiの「PRCCNT」パラメーターは必要な値です。名前は誤解を招く可能性があり(合計プロセスジョブ数として)、サブプロセス数です。それは「ワンライナー」です(もちろん、「kBによって支払われる」はそれを半分のページに分割するかもしれません):

$ spawn/nowait command1
$ spawn/nowait command2
...
$waitall: if f$getjpi("","PRCCNT").gt.0 then pipe wait 0::.5 ; goto waitall
...

ポーリング間隔を適切な値に設定し、コマンドの実行時間に適切にします。もちろん、0.5秒は普遍的なものではありません。

于 2015-02-18T22:10:56.450 に答える