|
Hi Frank,
Hi folks, is there a way to monitor for QSH msg's in a clp that runs interactively? STRQSH CMD('FIND /CITIZENS/O0* > /QSYS.LIB/ZPGMR97.LIB/STDOUT.FILE/STDOUT.MBR')
There are about a million possible ways to answer this question :)First of all, the easiest way to fix the exact symptom you've encountered, is to code it this way:
STRQSH CMD('find /CITIZENS -name ''O0*'' > /QSYS.LIB/ZPGMR97.LIB/STDOUT.FILE/STDOUT.MBR')This tells the 'find' utility to search the /CITIZENS directory, and to print any file matching the pattern 'O0*'. If there aren't any, it'll simply output nothing (your STDOUT.MBR will have no records in it.)
The way you coded it, you've told QShell to get a list of files stanting with 'O0' and pass them all as separate parameters to the 'find' program. Then the find program is to read each file passed by QShell and print it. In other words, you've let QShell (rather than the 'find' program) do the searching -- find is just echoing the names that QSHELL returned. In my version, the 'find' utility does the work. Qshell passes it the directory name of /CITIZENS and the 'find' utility opens up that directory and searches for files that match the pattern.
The main benefit is that there won't be an error as long as the /CITIZENS directory exists.
However, that doesn't really answer your question, which was (on a more general level) how to monitor for errors in a QShell program invoked from a CL program -- so I'll tackle that next:
Normally when you run a CL command from a CL program, and that command fails, the failing command will send back an *ESCAPE message to let you know that it failed. That's the way things work in the CPF, OS/400, i5/OS paradigm of running commands.
However, Unix doesn't have *ESCAPE messages -- again, that's an i5/OS thing, not a Unix thing. Unix programs have a different method of letting the caller know tha they failed. They set a return value. When the return value is set to 0, it means the command was successful. When it's set to a higher number, it means it failed. Programmers are free to set the return value to different numbers in order to distinguish different errors, but there's really no standard to what these numbers are, other than 0 means success -- and not every programmer even follows that standard!
Therefore if you try to do the following, it won't work: STRQSH CMD('find /CITIZENS/O0* > + /QSYS.LIB/ZPGMR97.LIB/STDOUT.FILE/STDOUT.MBR') MONMSG QSH0000Tt won't work because the 'find' utility is a Unix program, and doesn't send back an *ESCAPE message. Therefore, there's no message to monitor for!
Starting with V5R2, IBM added a new feature to QShell that lets QShell convert the return status of the program into a monitorable error. When QShell runs the 'find' program, it checks the return value. If it's zero, QShell sends you an *ESCAPE message, thus making the unix utility work something like a CL program expects tit to.
To enable that feature, do this before starting QShell: ADDENVVAR ENVVAR(QIBM_QSH_CMD_ESCAPE_MSG) VALUE(Y)QShell will look for that variable. If it's set, it'll send back an escame message if the find utility returns a number other than zero. (it can be QSH0005, QSH0006 or QSH0007)
You can use the RCVMSG command to retrieve the error message and check the status number, as well. For example, the following would monitor for an error and extract the return value (also called "status code") that the find utility has returned:
ADDENVVAR ENVVAR(QIBM_QSH_CMD_ESCAPE_MSG) + VALUE(Y) + REPLACE(*YES) STRQSH CMD('find /CITIZENS -name ''O0*'' -type f > + /QSYS.LIB/ZPGMR97.LIB/STDOUT.FILE/STDOUT.MBR') MONMSG MSGID(QSH0005) EXEC(DO) RCVMSG MSGTYPE(*LAST) RMV(*YES) MSGDTA(&MSGDTA) + MSGID(&MSGID) CHGVAR VAR(&STATUS) VALUE(%BIN(&MSGDTA 1 4)) ENDDOThis way, no matter which error occurs, your CL program will trap it and handle it appropriately. If you also want to suppress any output to the screen, there's another variable for that:
ADDENVVAR ENVVAR(QIBM_QSH_CMD_OUTPUT) VALUE(NONE) REPLACE(*YES)This suppresses anything displaying on the screen, which may be helpful, depending on what you're doing.
If you do not have V5R2 or later available to you, then you have to do it "the unix way" (which is more difficult to deal with from a CL program, but it's possible.)
On a Unix command-line, you can specify && to describe the name of a command that's run when something succeeds, or || to describe the name of a command that's run when it fails.
For example: ls /blah && echo "success"This'll try to list out the "/blah" subdirectory. If it succeeds (that is, returns a status of zero) it'll run the "echo" utility to print the word "Success".
On the other hand: ls /blah || echo "failed"This is similar, but it only prints the word "failed" if the ls command didn't succeed (returned a status not equal to zero)
Furthermore, you can redirect output from a QShell command. In fact, you used that capability in your example code to output filenames to a physical file member. You can also use it to suppress error messages Error messages are output to descriptor 2 rather than descriptor 1 (which is the default) so you'd redirect them as follows:
ls /blah 2> /dev/nullThat causes error messages to be discarded (actually, it writes them to a special file called "/dev/null" -- /dev/null is a special file that discards anything written to it.)
So on a pre-V5R2 system you could potentially detect failure and suppress output by doing this:
STRQSH CMD('(find /CITIZENS -name ''/O0*'' || echo "failed" > + /QSYS.LIB/ZPGMR97.LIB/STDOUT.FILE/STDOUT.MBR) 2> /dev/null')If it fails, the STDOUT member would have one record containing the word "failed". If it succeeds, it'll have zero or more pathnames that start with /CITIZENS.
Should be easy enough to use that to determine success or failure from the CL program.
Hope that helps...
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.