Operating System - OpenVMS
1828352 Members
2984 Online
109976 Solutions
New Discussion

Re: DCL command 'SUBMIT' exit status check

 
SOLVED
Go to solution
Joost van der Knaap
Occasional Advisor

DCL command 'SUBMIT' exit status check

Hi all,

This concerns a DCL script that resubmits itself.
I would like to verify the exit status of the submit command executed by the script.

Relevant code:
$ PIPE 'SUBMITCMD' | (read sys$pipe p9 ; DEF/JOB P9 &P9)
$ RESULT = f$trnlnm("P9")
$ IF F$LOCATE ("Job CDRC",RESULT) .NES. F$LENGTH(RESULT)
$ THEN
$ CALL LOGTHIS "''RESULT'" "IN"
$ ELSE
$ CALL LOGTHIS "''RESULT'" "ER"
$ ENDIF

Where IN and ER reflect the severity (IN = informational, ER = error). I'm wondering if the test conditions are sufficient. This should depend on whether or not the return messages of SUBMIT can also start with 'Job CDRC' for any kind of failure. I don't think it does, as I expect failures to be logged in system messages formatting (%facility-s-identification, text).

Is there a list of possible exit messages for SUBMIT?
19 REPLIES 19
Craig A
Valued Contributor

Re: DCL command 'SUBMIT' exit status check

Joost

Can you not just check $STATUS of the SUBMIT?

$ SUBMIT <script>
$ STATUS := '$STATUS'
$ IF STATUS
$ THEN
$ ! Success processing
$ ELSE
$ ! Failure processing
$ ENDIF

Craig
Joost van der Knaap
Occasional Advisor

Re: DCL command 'SUBMIT' exit status check

Hi Craig,

I could, but I would like to log the exact message.
Craig A
Valued Contributor

Re: DCL command 'SUBMIT' exit status check

Joost

Can you please explain what you are ultimately trying to achieve?

You could redirect sys$output to a temporary logfile and then interrogate that:

$ DEFINE/USER SYS$OUTPUT SUBMIT.LIS
$ DEFINE/USER SYS$ERROR SUBMIT.LIS
$ SUBMIT <script>

Craig
Joost van der Knaap
Occasional Advisor

Re: DCL command 'SUBMIT' exit status check

Goal 1: Differentiate between success and failure of SUBMIT.
Status: Fully met?

Goal 2: Be able to see in the log why a SUBMIT command failed.
Status: Fully met through subroutine LOGTHIS

Goal 3 (ultimate): solution combining goal 1 and goal 2.
Status: Fully met?

As you said, goal 1 can be achieved through $STATUS, but then I would not capture the error reason to feed it to the LOGTHIS subroutine.

The main reason why I started this thread was to learn whether or not I have already met goal 1 by checking the return string for the text 'Job CDRC'. The docs on system error messages and on the SUBMIT command I've found haven't convinced me that there couldn't be an error condition that would result in a string that passes the F$LOCATE check.

I kind of like the method of storing the returned string as a logical instead of a temporary logfile.
Craig A
Valued Contributor

Re: DCL command 'SUBMIT' exit status check

Joost

Can you not just pass SUBMIT.LIS through to the subroutine LOGTHIS to do something useful with it?

Craig
Joseph Huber_1
Honored Contributor
Solution

Re: DCL command 'SUBMIT' exit status check

Why not combine status check and output logging ?
Instead
$ IF F$LOCATE ("Job CDRC",RESULT) .NES. F$LENGTH(RESULT)
use
$if f$integer($SEVERITY).eq.1

and leave anything else as is, but do not derive success/error from a particular output string.
http://www.mpp.mpg.de/~huber
Joseph Huber_1
Honored Contributor

Re: DCL command 'SUBMIT' exit status check

In addition:
if You really want to log the full submit error message in a separate log-file, then a single read is not enough: those usually are two lines, example:

MPIW10_HUB>pipe submit xyz | (read sys$pipe p9 ; DEF/JOB P9 &P9)
MPIW10_HUB>sh log p9
"P9" = "%SUBMIT-F-OPENIN, error opening DISK$HUBER:[HUBER.SOURCES.C]xyz.COM; as input" (LNM$JOB_81838080)
MPIW10_HUB>submit xyz
%SUBMIT-F-OPENIN, error opening DISK$HUBER:[HUBER.SOURCES.C]xyz.COM; as input
-RMS-E-FNF, file not found

The single read from pipe only gets the %SUBMIT-F line, the important second line giving the reason (-RMS-E-FNF...) is not logged!
http://www.mpp.mpg.de/~huber
Craig A
Valued Contributor

Re: DCL command 'SUBMIT' exit status check

Also, if it wer me, I'd be performing validation of certain things before doing the actual SUBMIT:

Username (if /USER I BEING USEd)
Filename - F$SEARCH
Queue - Exist? in started state?

Craig
Joost van der Knaap
Occasional Advisor

Re: DCL command 'SUBMIT' exit status check

@Joseph:
Thanks for suggesting f$integer($SEVERITY). I didn't even try that as I thought it would no longer relate to SUBMIT due to the stuff that happens between it and the IF statement.

@Craig:
Valid points. In my case resubmitting is pretty much the first thing it does so I can be reasonably sure the file still exists as does the user.
Joseph Huber_1
Honored Contributor

Re: DCL command 'SUBMIT' exit status check

>> I didn't even try that as I thought it would no longer relate to SUBMIT due to the stuff that happens between it and the IF statement.

And You are right to think so: $STATUS/$SEVERITY is that after the pipe, not what You want.

The only solution I can see is to write the SUBMIT command message into a temporary file, and chain the command with an command-file, which saves the $STATUS/$SEVERITY, then reads and logs the temporary file:

$ PIPE SUBMIT ... >tempfile ; @logit tempfile

"PIPE ; " does not create a subprocess (no sys$pipe), but has valid $STATUS in @logit.
"PIPE | " creates a subprocess with sys$pipe, but then $STATUS is not available.
http://www.mpp.mpg.de/~huber
Joost van der Knaap
Occasional Advisor

Re: DCL command 'SUBMIT' exit status check

In that case I think I might follow some of Craig's suggestions and do something like this:

$ DEFINE/JOB SYS$OUTPUT SUBMIT.LIS
$ DEFINE/JOB SYS$ERROR SUBMIT.LIS
$ 'SUBMITCMD'
$ STATUS := "''$status' ''$severity'"
$ SHOW SYMBOL STATUS
$ DEASSIGN/JOB SYS$OUTPUT
$ DEASSIGN/JOB SYS$ERROR

And then open the file to determine the results.

Either way it seems I'm not going to avoid additional I/O and a cleanup subroutine for temp files.
Craig A
Valued Contributor

Re: DCL command 'SUBMIT' exit status check

Joost

If you use /USER rather then /JOB then the definition only remains in place for the next image activAtion. In this case the use of SUBMIT.EXE

So you don't need to DEASSIGN the logicals.

Craig
Hoff
Honored Contributor

Re: DCL command 'SUBMIT' exit status check

Jess Goodman
Esteemed Contributor

Re: DCL command 'SUBMIT' exit status check

There are a couple of cases where SUBMIT outputs an informational message before the line that has "JOB jobname".

$ SUBMIT LOGIN /NOLOG /RETAIN=UNTIL=YESTERDAY
%JBC-I-ITMREMOVED, meaningless items were removed from request
Job LOGIN (queue SYS$BATCH_AX38, entry 2003955) started on SYS$BATCH_AX38

These would cause your test of the first output line for the string "JOB jobname" to fail.


I have one, but it's personal.
Joseph Huber_1
Honored Contributor

Re: DCL command 'SUBMIT' exit status check

Just to add another solution avoiding a temporary file:

pipe (submit xyz ; write sys$output "SEV: ",$severity) | @logit

This puts the severity of the SUBMIT as last line to the output pipe.
So logit.com can do a read loop on sys$pipe, and check for a line starting with "SEV:" to handle the results.
http://www.mpp.mpg.de/~huber
Joseph Huber_1
Honored Contributor

Re: DCL command 'SUBMIT' exit status check

The DCL code for the above solution could look like this:

$ me=f$environment("PROCEDURE")
$ if p1.eqs."#LOG#" then goto LOG

...

$ pipe (submit xyz ; write sys$output "SEV: ",$severity) | @'me' #LOG#

...

$LOG:
$ n=0
$LOOP:
$ read/end=DONE sys$pipe line
$ if f$extract(0,4,line).eqs."SEV:"
$ then
$ severity = f$element(1," ",line)
$ else
$ line'n' = line
$ n=n+1
$ endif
$ goto LOOP
$DONE:
$ tag="ER"
$ if f$integer(severity).eq.1 then tag="IN"
$ i=0
$LL:
$ result = line'i'
$ CALL LOGTHIS "''RESULT'" 'tag'
$ i=i+1
$ if i.lt.n then goto LL
$ exit
http://www.mpp.mpg.de/~huber
John Gillings
Honored Contributor

Re: DCL command 'SUBMIT' exit status check

Joost,

First to answer your direct question:

>Is there a list of possible exit
>messages for SUBMIT?

In theory, you might be able to work it out, but in practice, not really. Looking at the source of SUBMIT you may be able to find all the condition codes which are explicitly signalled or returned, but you then need to consider all the subsystems it calls - SYS$, RMS$, LCK$ and on and on. This becomes a very large, and somewhat unpredictable set. Even if you could construct such a set, it could potentially change in future, so you make yourself a maintenance task.

Onwards...

I think you're making this far more complex than necessary. As I see it there are two issues:

1) You want the procedure to detect if the SUBMIT was successful (or, more generally, any particular action in your procedure)

2) If an action fails you want to capture the exact and complete error message.

Your problem is you're trying to do both simultaneously, which is leading to convoluted code to try and account for many possibilities (for example, multiple lines of error message). This also adds extra things that might fail, and thus you recurse into a cascade of checks upon checks upon checks.

Try tackling each issue separately. 1 is simple, use $STATUS

$ SUBMIT ...whatever
$ stat=$STATUS
$ IF stat
$ THEN
$ ...OK
$ ELSE
$ ...Failed
$ ENDIF

Simple!

For 2, realise that the error message is complete and intact in the log file of the batch job. You can log that an error occurred, including the primary status. You can also add a pointer to the log file containing the completetext:

$ IF F$GETQUI("DISPLAY_ENTRY","JOB_LOG_NULL",,"THIS_JOB")
$ THEN
$ Msg = "(no log file)"
$ ELSE
$ Msg = "See Logfile:"+F$PARSE(F$GETQUI("DISPLAY_ENTRY","LOG_SPECIFICATION",,"THIS_JOB"),-
"SYS$LOGIN:.LOG;",F$GETQUI("DISPLAY_ENTRY","JOB_NAME",,"THIS_JOB"))
$ ENDIF
$ out=F$FAO("!AS: !UL error!%S in !AS on node !AS. !AS",Name,Err,Title,Node,Msg)

(in this example, I count the number of errors that occurred in symbol "Err" - the message is then MAILed at the end of the job.

To further highlight any issues, I usually submit jobs with /RETAIN=ERROR, and track the worst status value in symbol "stat". Last line is:

$ EXIT %X10000000.OR.F$INTEGER(stat)+(F$VERIFY(verf).AND.0)

"verf" contains the verification value on entry, stat is the completion code, and %X10000000 sets the STS$M_INHIB bit to tell DCL not to display an error message.

I have a daily job that hunts for and reports on any retained jobs.
A crucible of informative mistakes
John Gillings
Honored Contributor

Re: DCL command 'SUBMIT' exit status check

Joost,
Taking another (more general) approach...

Since the error message is in the log file, which is periodically flushed, you can get the message live from the log file at run time with, for example, TYPE/TAIL, or any other command which can read a shared file. You can therefore use ON WARNING to collect error messages from ANY command which generates an error using a GOSUB so you don't interrupt the flow of execution. Try this:

CATCHWARN.COM
$ SET NOON
$ SET VERIFY
$ GOSUB SetupLog
$
$ WRITE SYS$OUTPUT "Some stuff in the log file"
$ SHOW PROCESS
$
$ WRITE SYS$OUTPUT "Now generate some errors"
$
$ TYPE junk.dat
$
$ SUBMIT/QUEUE=noqueue nojob
$
$ WRITE SYS$OUTPUT "More stuff in log file"
$ EXIT
$
$ SetupLog: v='F$VERIFY(0)'
$ outrate="0:0:01"
$ SET OUTPUT_RATE='outrate'
$ mylog=F$PARSE(F$GETQUI("DISPLAY_ENTRY","LOG_SPECIFICATION",,"THIS_JOB"),-
"SYS$LOGIN:.LOG;",F$GETQUI("DISPLAY_ENTRY","JOB_NAME",,"THIS_JOB"))
$ SHOW SYM mylog
$ OPEN/WRITE log SYS$LOGIN:OTHER.LOG
$ ON WARNING THEN GOSUB Logit
$ RETURN ! 'F$VERIFY(v)'
$
$ Logit: stat=$STATUS ! 'F$VERIFY(0)'
$ WAIT 'outrate'
$ WRITE log "Error status=''stat' at ''F$TIME()' Last 5 lines in ''mylog'"
$ WRITE log "-----"
$ PIPE TYPE/TAIL=5/HEADER 'mylog' > log
$ WRITE log "-----"
$ ON WARNING THEN GOSUB Logit
$ RETURN 1+0*F$VERIFY(v)

So, subroutine SetupLog finds the log file of the batch job, and creates a secondary log file. It also saves verification state and sets the output rate to a known value.
We then use:

$ ON WARNING THEN GOSUB Logit

to execute a subroutine any time a WARNING or higher condition occurs.

Subroutine Logit waits for the output rate period, to make sure any messages up to the warning event have been flushed to the log. It then writes a report line and dumps the last 5 lines of the file into the secondary log file. Finally it resets the ON WARNING condition and restores verification.

Note that the RETURN must return a success status, otherwise it will immediately call Logit again after returning (infinite loop). That means the only change from "normal" DCL in your mainline, is any additional processing of status needs to look at "stat" instead of $STATUS, (but you need to make sure an "old" value in "stat" isn't picked up later as it isn't automatically updated, like $STATUS).

Another option in communicating status back to the main line would be to use the unused success status 7 to indicate an error. So, the end of Logit could look like:

$ RETURN stat.OR.7+0*F$VERIFY(v)

Your mainline then knows an error or warning has occured if $SEVERITY is 7, and can retrieve the actual status (including the true severity) from "stat".

$ SUBMIT/QUEUE=noqueue nojob
$ IF $SEVERITY.EQ.7
$ THEN
$ WRITE SYS$OUTPUT "Submit failed - status ''stat'"
$ ENDIF

Have fun!
A crucible of informative mistakes
Joost van der Knaap
Occasional Advisor

Re: DCL command 'SUBMIT' exit status check

@everyone: Thanks for all the suggestions.
As usual in DCL, there seem to be plenty ways of going about it.

Per John Gillings' last remark - I'm off to have fun with this.