I am sure there are APIs that you can use to do this.
You may want to search this site and google it.
Bruce Vining may have had an article in MC Pres.
What I have done in the past is to do a WRKOUTQ myoutq *PRINT
Then copy the outut to a DB file and have a program read the file.
The file will look like this:
I pasted left side of page, then right side
<pre>
5770SS1 V7R1M0 100423 Work With Output Queue
File User User Data Status Pages Copies Form
QPQUPRFIL CHARLIEB RDY 1 1 *STD
MWI0891P CHARLIEB MWI0891 RDY 2 1 *STD
MWI0891P CHARLIEB MWI0891 RDY 2 1 *STD
BONBASLOG CHARLIEB RDY 3 1 *STD
BONBASEDB CHARLIEB RDY 11 1 *STD
CHARLIEB in QUSRSYS
Type Pty File Number Job Number Date Time
5 1 CROSS_LF 301975 02/27/12 05:31:20
5 3 CBDEV1 302227 02/27/12 14:03:54
5 4 CBDEV1 302227 02/27/12 14:14:57
5 1 BONBASLOG 308084 02/28/12 12:29:25
5 1 BONBASEDB 308510 02/28/12 13:50:48</pre>
Last Wiki Answer Submitted: March 7, 2012 2:23 pm by CharlieBrowne32,855 pts.
All Answer Wiki Contributors: CharlieBrowne32,855 pts.
If you live outside the United States, by submitting your email address you consent to having your personal data transferred to and processed in the United States.
If you don’t already have the following program and command, I use it frequently to as the first step to get the spooled file information into a physical file where I can then process the information from the physical file.
Best way I know of to retrieve spool file information is to use the QUSLSPL API with format SPLF0200. This will list the contents of the specified output queue and, using the key field, you can get all the information you need about the spool file in question (including status).
(Not that CharlieBrown’s method doesn’t work, but I hate copying spool files then parsing the output)
If you have TAATOOLS there is a command CHGALLSPLF which allows all spooled files in an output queue to be changed for such values as OUTQ, FORMTYPE, SAVE, and ALIGN. This provides a command infterface instead of using the ’2′ option on WRKOUTQ. A hold/release option also exists. The current status of the spooled files to be considered is an option in the command parameters. The one caveat is that you must have *jobctl special authority to use this command.
How can I schedule a job to move a spool file after it gets printed.
AFAIK, there is no way to “schedule” such a job. You could, however, have an automated response to the event, and maybe that’s what you’re asking.
Assuming you are auditing print activity, you can have a batch program watching for T/PO entries in the system audit journal QAUDJRN. When it sees such an entry, it would check for Output Type=’S’ (Spooled file printed) together with Status After Printing=’S’ (Saved after printed). And by checking other values, such as the name of the spooled file or whatever, your program what take whatever action you wanted it to do.
You would code a CL program that uses RCVJRNE to control the process. You’d also code a second program that the command calls through its EXITPGM() parameter to handle the individual journal entries.
Submit the CL program to job queue QUSRNOMAX or some other queue where it can run as long as you need it to.
One way I can think of is attaching a DTAQ to the OUTQ in question. This DTAQ should be monitored by a program running in BATCH. The DTAQ attached to the OUTQ receives an entry each time a spooled file on the OUTQ changes status. The DTAQ support is OS, so nothing else to do than to change the description of the output queue. As to the format of the data queue entry you will need to research that.
PGM8888 reads the file and get status an age and call other programs to delete ot move the spoolfiles to a SVOUTQ to avoid clutter in working outqs. The program are set to delete if over the # of days specified in the parm. This program is currently called by another program with a list of outqs and #_o_f days_ old and is in our schedule to run 1 time each hour from about 7:AM to 8:PM
This :
D DS
DSPFDTA 1 132
D FILE 2 11
D USER 13 22
D STATUS 36 40
D FILE# 73 78
D FL# 73 78
D DIM(6)
D JOBNAME 84 91
D JOBNUM 95 100
D JOBDAT 102 109
D JOBDMM 102 103
D JOBDDD 105 106
D JOBDYY 108 109
D DS
D CVTDAT 1 6 0
D CVTDYY 1 2 0
D CVTDMM 3 4 0
D CVTDDD 5 6 0
D CHKDTE2 1 6 0
D FILE#2 1 6
D FL#2 1 6
D DIM(6)
D*
D TODAY S D DATFMT(*ISO) INZ(D'0001-01-01') ISO YYYY.MM.DD
D CHKDTE S D DATFMT(*ISO) INZ(D'0001-01-01') ISO YYYY.MM.DD
D CVTDTE2 S D DATFMT(*ISO) INZ(D'0001-01-01') ISO YYYY.MM.DD
*------------------------------------------------------------------------*
DPPARMS PLIST
PARM FILE
PARM JOBNAME
PARM USER
PARM JOBNUM
PARM FILE#2
is used by PGM88888 to determine age and status to call a program to delete or move it.
Non fancy but it gets the job done. If we had to write it now i would have the control program read a file with From_outq, To_outq, and days_to_sav instead of hardcoding it in the control program.
One way I can think of is attaching a DTAQ to the OUTQ in question.
Unfortunately, a data queue won’t help for this question. The data queue receives entries when spooled files go to RDY status. This question is looking for a way to signal the SAV status after a writer has processed the file.
A journal event is the only signal available.
The examples of listing an output queue would work for a never-ending program, although they’re pretty heavy for the task.
The QUSLSPL API mentioned by Splat is a better way to go if a signal/event is going to be avoided. If the spooled file had a meaningful form type or unique ‘User-specified data’, the programming would be pretty straightforward. It wouldn’t be too much even if those weren’t available.
Observation about Audit Journal entries – The PO audit journal entries were not created on my system when I printed IBM reports. I did however get SF entries which provided all of the information I needed. Thanks for the tip on audit journal entries.
Questions – What generates PO entries – possible files that go directly to the printer without creating a spool file first?
PO entries should be sent if the QAUDCTL system value includes *PRTDTA. The SF entries would be sent if *SPLFDTA is included.
The SF entries should actually be what would signal the change in status. But the PO signals that printing (writer processing) had been done. Technically, I suppose, the current question is actually looking for the combination of the two — printing followed by SAV status change.
The spooled file may have status changes without being printed. Printing should always cause a change in status.
If you don’t already have the following program and command, I use it frequently to as the first step to get the spooled file information into a physical file where I can then process the information from the physical file.
Program CVTPRTPF Convert Print to physical file
/********************************************************************/ /* Program name . . . . . . . . . . . . . . : PRT004CL */ /* Author . . . . . . . . . . . . . . . . . : Raymond G. Johnson */ /* Date created . . . . . . . . . . . . . . : 10/01/2000 */ /* */ /* Program information: Convert Spool file to physical file */ /* */ /* */ /********************************************************************/ /* Change log: */ /********************************************************************/ /* Date Initials Change Description */ /********************************************************************/ /* 10.01.2001 RGJ */ /* */ /* */ /********************************************************************/ PGM PARM(&CMD &PRTF &QF &MEMBER) DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(80) DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) DCL VAR(&CMD) TYPE(*CHAR) LEN(3000) DCL VAR(&FILE) TYPE(*CHAR) LEN(10) DCL VAR(&LIB) TYPE(*CHAR) LEN(10) DCL VAR(&MBR) TYPE(*CHAR) LEN(10) DCL VAR(&MBROPT) TYPE(*CHAR) LEN(8) DCL VAR(&MEMBER) TYPE(*CHAR) LEN(20) DCL VAR(&PRTF) TYPE(*CHAR) LEN(10) DCL VAR(&QF) TYPE(*CHAR) LEN(20) /********************************************************************/ /* Global Monitor Message - Standard error exit */ /********************************************************************/ MONMSG MSGID(CPF0000 MCH0000) EXEC(GOTO CMDLBL(ERROR)) /********************************************************************/ /* Start of program. */ /********************************************************************/ CHGVAR VAR(&FILE) VALUE(%SST(&QF 1 10)) CHGVAR VAR(&LIB) VALUE(%SST(&QF 11 10)) CHGVAR VAR(&MBR) VALUE(%SST(&MEMBER 3 10)) CHGVAR VAR(&MBROPT) VALUE(%SST(&MEMBER 13 8)) CHKOBJ OBJ(&LIB/&FILE) OBJTYPE(*FILE) MONMSG MSGID(CPF9898) EXEC(DO) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) + MSGDTA('LIBRARY' *BCAT 'not found') + MSGTYPE(*ESCAPE) RETURN ENDDO MONMSG MSGID(CPF9801) EXEC(DO) CRTPF FILE(&LIB/&FILE) RCDLEN(512) ENDDO CHKOBJ OBJ(&LIB/&FILE) OBJTYPE(*FILE) MBR(&MBR) MONMSG MSGID(CPF9815) EXEC(DO) ADDPFM FILE(&LIB/&FILE) MBR(&MBR) ENDDO OVRPRTF FILE(&PRTF) HOLD(*YES) CALL PGM(QCMDEXC) PARM(&CMD 3000) MONMSG MSGID(CPF0000) EXEC(DO) SNDPGMMSG MSG(&CMD *BCAT 'failed') RETURN ENDDO CPYSPLF FILE(&PRTF) TOFILE(&LIB/&FILE) JOB(*) + SPLNBR(*LAST) DLTSPLF FILE(&PRTF) JOB(*) SPLNBR(*LAST) + SELECT(*CURRENT) DLTOVR FILE(&PRTF) RETURN: RETURN /********************************************************************/ /* END OF PROGRAM / ERROR EXIT */ /********************************************************************/ ERROR: RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) + MSGID(&MSGID) MONMSG MSGID(CPF0000) SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*ESCAPE) MONMSG MSGID(CPF0000) END: ENDPGMCommand for program:
/********************************************************************/ /* Program name . . . . . . . . . . . . . . : PRT004CL */ /* Author . . . . . . . . . . . . . . . . . : Raymond G. Johnson */ /* Date created . . . . . . . . . . . . . . : 10/01/2000 */ /* */ /* Program information: Convert Spool file to physical file */ /* */ /* */ /********************************************************************/ /* Change log: */ /********************************************************************/ /* Date Initials Change Description */ /********************************************************************/ /* 10.01.2001 RGJ */ /* */ /* */ /********************************************************************/ PGM PARM(&CMD &PRTF &QF &MEMBER) DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(80) DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) DCL VAR(&CMD) TYPE(*CHAR) LEN(3000) DCL VAR(&FILE) TYPE(*CHAR) LEN(10) DCL VAR(&LIB) TYPE(*CHAR) LEN(10) DCL VAR(&MBR) TYPE(*CHAR) LEN(10) DCL VAR(&MBROPT) TYPE(*CHAR) LEN(8) DCL VAR(&MEMBER) TYPE(*CHAR) LEN(20) DCL VAR(&PRTF) TYPE(*CHAR) LEN(10) DCL VAR(&QF) TYPE(*CHAR) LEN(20) /********************************************************************/ /* Global Monitor Message - Standard error exit */ /********************************************************************/ MONMSG MSGID(CPF0000 MCH0000) EXEC(GOTO CMDLBL(ERROR)) /********************************************************************/ /* Start of program. */ /********************************************************************/ CHGVAR VAR(&FILE) VALUE(%SST(&QF 1 10)) CHGVAR VAR(&LIB) VALUE(%SST(&QF 11 10)) CHGVAR VAR(&MBR) VALUE(%SST(&MEMBER 3 10)) CHGVAR VAR(&MBROPT) VALUE(%SST(&MEMBER 13 8)) CHKOBJ OBJ(&LIB/&FILE) OBJTYPE(*FILE) MONMSG MSGID(CPF9898) EXEC(DO) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) + MSGDTA('LIBRARY' *BCAT 'not found') + MSGTYPE(*ESCAPE) RETURN ENDDO MONMSG MSGID(CPF9801) EXEC(DO) CRTPF FILE(&LIB/&FILE) RCDLEN(512) ENDDO CHKOBJ OBJ(&LIB/&FILE) OBJTYPE(*FILE) MBR(&MBR) MONMSG MSGID(CPF9815) EXEC(DO) ADDPFM FILE(&LIB/&FILE) MBR(&MBR) ENDDO OVRPRTF FILE(&PRTF) HOLD(*YES) CALL PGM(QCMDEXC) PARM(&CMD 3000) MONMSG MSGID(CPF0000) EXEC(DO) SNDPGMMSG MSG(&CMD *BCAT 'failed') RETURN ENDDO CPYSPLF FILE(&PRTF) TOFILE(&LIB/&FILE) JOB(*) + SPLNBR(*LAST) DLTSPLF FILE(&PRTF) JOB(*) SPLNBR(*LAST) + SELECT(*CURRENT) DLTOVR FILE(&PRTF) RETURN: RETURN /********************************************************************/ /* END OF PROGRAM / ERROR EXIT */ /********************************************************************/ ERROR: RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) + MSGID(&MSGID) MONMSG MSGID(CPF0000) SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*ESCAPE) MONMSG MSGID(CPF0000) END: ENDPGMBest way I know of to retrieve spool file information is to use the QUSLSPL API with format SPLF0200. This will list the contents of the specified output queue and, using the key field, you can get all the information you need about the spool file in question (including status).
(Not that CharlieBrown’s method doesn’t work, but I hate copying spool files then parsing the output)
If you have TAATOOLS there is a command CHGALLSPLF which allows all spooled files in an output queue to be changed for such values as OUTQ, FORMTYPE, SAVE, and ALIGN. This provides a command infterface instead of using the ’2′ option on WRKOUTQ. A hold/release option also exists. The current status of the spooled files to be considered is an option in the command parameters. The one caveat is that you must have *jobctl special authority to use this command.
How can I schedule a job to move a spool file after it gets printed.
AFAIK, there is no way to “schedule” such a job. You could, however, have an automated response to the event, and maybe that’s what you’re asking.
Assuming you are auditing print activity, you can have a batch program watching for T/PO entries in the system audit journal QAUDJRN. When it sees such an entry, it would check for Output Type=’S’ (Spooled file printed) together with Status After Printing=’S’ (Saved after printed). And by checking other values, such as the name of the spooled file or whatever, your program what take whatever action you wanted it to do.
See the PO (Printer Output) journal entries page in the Information Center. Or look at Appendix F of a Security Reference manual.
You would code a CL program that uses RCVJRNE to control the process. You’d also code a second program that the command calls through its EXITPGM() parameter to handle the individual journal entries.
Submit the CL program to job queue QUSRNOMAX or some other queue where it can run as long as you need it to.
Tom
One way I can think of is attaching a DTAQ to the OUTQ in question. This DTAQ should be monitored by a program running in BATCH. The DTAQ attached to the OUTQ receives an entry each time a spooled file on the OUTQ changes status. The DTAQ support is OS, so nothing else to do than to change the description of the output queue. As to the format of the data queue entry you will need to research that.
We use a group of programs to move to a SVOUTQ or delete all SAV files in all working outqs.
OVRPRTF FILE(QPRTSPLQ) HOLD(*YES) USRDTA(RMVSPLF) + SPLFNAME(RMVSPLF) WRKOUTQ OUTQ(&OUTQ) OUTPUT(*PRINT) MONMSG MSGID(CPF3357) EXEC(GOTO CMDLBL(SKIP)) CPYSPLF FILE(RMVSPLF) TOFILE(PGM8888PF) SPLNBR(*LAST) DLTSPLF FILE(RMVSPLF) SPLNBR(*LAST) SELECT(*CURRENT + *ALL *ALL RMVSPLF) CALL PGM(PGM8888) PARM(&DYSOLD)PGM8888 reads the file and get status an age and call other programs to delete ot move the spoolfiles to a SVOUTQ to avoid clutter in working outqs. The program are set to delete if over the # of days specified in the parm. This program is currently called by another program with a list of outqs and #_o_f days_ old and is in our schedule to run 1 time each hour from about 7:AM to 8:PM
This :
D DS DSPFDTA 1 132 D FILE 2 11 D USER 13 22 D STATUS 36 40 D FILE# 73 78 D FL# 73 78 D DIM(6) D JOBNAME 84 91 D JOBNUM 95 100 D JOBDAT 102 109 D JOBDMM 102 103 D JOBDDD 105 106 D JOBDYY 108 109 D DS D CVTDAT 1 6 0 D CVTDYY 1 2 0 D CVTDMM 3 4 0 D CVTDDD 5 6 0 D CHKDTE2 1 6 0 D FILE#2 1 6 D FL#2 1 6 D DIM(6) D* D TODAY S D DATFMT(*ISO) INZ(D'0001-01-01') ISO YYYY.MM.DD D CHKDTE S D DATFMT(*ISO) INZ(D'0001-01-01') ISO YYYY.MM.DD D CVTDTE2 S D DATFMT(*ISO) INZ(D'0001-01-01') ISO YYYY.MM.DD *------------------------------------------------------------------------* DPPARMS PLIST PARM FILE PARM JOBNAME PARM USER PARM JOBNUM PARM FILE#2is used by PGM88888 to determine age and status to call a program to delete or move it.
Non fancy but it gets the job done. If we had to write it now i would have the control program read a file with From_outq, To_outq, and days_to_sav instead of hardcoding it in the control program.
.
One way I can think of is attaching a DTAQ to the OUTQ in question.
Unfortunately, a data queue won’t help for this question. The data queue receives entries when spooled files go to RDY status. This question is looking for a way to signal the SAV status after a writer has processed the file.
A journal event is the only signal available.
The examples of listing an output queue would work for a never-ending program, although they’re pretty heavy for the task.
The QUSLSPL API mentioned by Splat is a better way to go if a signal/event is going to be avoided. If the spooled file had a meaningful form type or unique ‘User-specified data’, the programming would be pretty straightforward. It wouldn’t be too much even if those weren’t available.
Tom
Observation about Audit Journal entries – The PO audit journal entries were not created on my system when I printed IBM reports. I did however get SF entries which provided all of the information I needed. Thanks for the tip on audit journal entries.
Questions – What generates PO entries – possible files that go directly to the printer without creating a spool file first?
What generates PO entries -
PO entries should be sent if the QAUDCTL system value includes *PRTDTA. The SF entries would be sent if *SPLFDTA is included.
The SF entries should actually be what would signal the change in status. But the PO signals that printing (writer processing) had been done. Technically, I suppose, the current question is actually looking for the combination of the two — printing followed by SAV status change.
The spooled file may have status changes without being printed. Printing should always cause a change in status.
Tom