ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

QPSHELL/QPSHELL2 errors and QPRINT

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • QPSHELL/QPSHELL2 errors and QPRINT

    Hello.

    I have a CL program that is calling QP2SHELL to list files from the IFS. If I specify a pattern and there is no match, QP2SHELL writes to QPRINT with an error message.

    Is is possible to turn this off? I don't want printer output from a failed QP2SHELL/QP2SHELL2 command.

    Thanks in advance,

    Mike
    Last edited by mlopez01; March 16, 2017, 01:28 PM.

  • #2
    Hello,

    This is hard to answer since I'm not familiar with your program's requirements. There are several different approaches, here... and to know which one to use, you have to know the program that you're running and how it expects the environment to be set up. I'll try to explain the situation and what the different approaches are. Apologies, but this will be a somewhat long answer, since I'm trying to explain every situation that
    I can think of and how it would be handled.

    It's very common for Unix programs to expect three data streams called "standard input" ("stdin", fd=0), "standard output" ("stdout", fd=1), and "standard error" ("stderr", fd=2). Not all Unix programs work this way, but it is extremely commonplace. stdin is used for reading data into the program, on a Unix system it defaults to reading from the keyboard, but can be redirected to a pipe or file. stdout is where the Unix program writes its normal output, by default this is text displayed on the screen, but it also can be redirected to a pipe or file. stderr is where the program writes its error messages... just like stdout, it goes to the screen, but can be redirected to a file or pipe. stderr and stdout are separate streams because it's often useful to redirect errors to a different place from normal output.

    QP2SHELL will simply run the program in your current job. It does not set up these streams (or anything else) for you! It just loads and runs the program in your job. QP2SHELL uses a new activation group, whereas QP2SHELL2 runs in the caller's activation group.

    1) If you have opened up pipes or files that are connected to these streams, it will use them. QP2SHELL does not do that for you, though.

    2) Otherwise, it falls back to trying to use the ILE C versions of these streams. This is not ideal, as they are not threadsafe and therefore can cause some Unix programs to go awry. You need to know whether your application works this way so it can be handled properly.

    3) If using the ILE streams, they will not always be connected to an fd. So you need to know if your Unix program requires an fd, or can just write to the stream via the symbolic names stdin,stdout, or stderr. (Otherwise, set up the ILE envionment to be sure fds 0-2 are open). Otherwise things can go awry if your program needs the fds.

    4) If run from ann environment where there is no display (e.g. a batch job), the ile stdout/stderr streams will by default be redirected to a spooled file. This is probably where your QPRINT is coming from.

    So you either need to set up the whole Unix environment, or want to be minimal about it (to use fewer resources, etc) then you need to know exactly what your program requires.

    To set up the whole enviroment takes a fair amount of work if you code it yourself.
    1) Create 3 pipes, stream files, or sockets. (via the pipe(), open() or socket() APIs)
    2) Use the spawn() API to create a job that connects the fds of these pipes, files or sockets to fds 0,1,2 of the spawned job.
    3) Run the QP2SHELL API in the spawned job.

    Or, you can use the QShell (not to be confused with QP2SHELL) environment, which sets this up for you automatically. QShell is run via the STRQSH or QSH command. This does the steps above, but it's doen for you under the covers.

    Setting up the whole environment like this can be slow, especially since you need to spawn new jobs. If your program is okay to use with the ILE streams (this is where you need to know about your program) you can run it directly with QP2SHELL. In this case you may (or may not) need to have fds 0,1,2 already open in the job. Again, this requires knowing what your program needs.

    If you do use the ILE approach (with or without fds open) you can use OVRDBF FILE(STDOUT) or OVRDBF FILE(STDERR) (or equivalent OVRPRTF) to redirect that output. So if that is adequate, you could override to a temp file in QTEMP and delete it afterwards (for example).

    FINALLY... one more approach is to use QP2SHELL to spawn a shell (rather than the program directly) and use the shell's capabiities to redirect stdout/stderr, etc. Again, you need to know whether this would work for your program, but this would usually work... but, there are situations where this would be inefficient because it runs multiple processes (both the shell and the program...)

    Comment


    • #3
      The simple answer if you just want to use that last approach and not really understand what you're doing or which way is the most efficient for your application is to do this:

      Code:
      CALL QP2SHELL PARM('/QOpenSys/usr/bin/sh' '-c' 'Your Command 2> /dev/null')
      The 2> /dev/null redirects stderr to /dev/null (which discards the error message -- a terrible approach, throwing away the error, but that is what you asked for)

      Or if you want to discard both stderr and stdout:
      Code:
      CALL QP2SHELL PARM('/QOpenSys/usr/bin/sh' '-c' 'Your Command &> /dev/null')

      Comment


      • #4
        Hi, Scott. Thank you for this.

        Comment

        Working...
        X