Integrate Python, Node, PHP, etc. with CL & RPG on IBM i – 2023 Update

A few years ago I introduced you to my QShell on i utility – QSHONI. QSHONI makes it easy for traditional CL, RPG, and COBOL programs to call Python utilities and other QShell/PASE utility programs (PHP, Node, Java, etc.) and directly use their output. QSHONI opened up a whole new world of integrations to open source apps from RPG, CL, and COBOL.

In this post I will update you on new features that have been added to the QSHONI utilities over the past 12 months.

As a reminder, if you are still using the PYRUN command to run Python apps, consider migrating to QSHONI’s QSHPYRUN or QSHEXEC commands. PYRUN still works, but it is no longer being maintained.

Write or Append STDOUT to an IFS File

Logging to IFS files has now become easier. The core QSHONI commands—QSHEXEC, QSHBASH and QSHPYRUN—now support a parameter named IFSSTDOUT. The new parameter allows each command to write or append its STDOUT (standard output) to an app-specific, IFS-based log file.

Writing or appending to an app-specific IFS log file can be useful if you want to use print statements in your Python (or other) code to output useful info to STDOUT, and then use that info for logging the success or failure of your Python or other language scripts. IFS log files can be visually reviewed or read by log readers and other tools to review success or failure events. This option adds maximum flexibility for STDOUT logging.

Python Virtual Environments

The QSHPYRUN command now supports Python virtual environments for running Python apps that belong to a virtual environment. Simply set the “use virtual environment” parameter to *YES and then specify the “virtual environment base path” directory parameter, and your Python app will be called using the selected Python virtual environment.

Easily Pass Parameters to curl

Curl is the popular open source program for sending and receiving content from APIs and many other sources, internal and external. For developers who want to call curl conveniently, QSHCURL is essentially a front end over the QSHEXEC command that allows an RPG or CL developer to easily call the PASE curl command with parameters. As soon as curl finishes its processing, the program output can be utilized directly from a classic CL/RPG program by reading the output file (outfile) contents from file STDOUTQSH in library QTEMP or by consuming any IFS output files that were created for logging.

A good example use case for calling QSHCURL might be to place a call to an external web service and then consume the HTML, XML or JSON result data that gets returned from the QSHCURL call.  This can provide much more flexibility than using the db2 HTTPCLOB functionality to make rest API calls. Curl is like a swiss army knife of connectivity so it’s great to be able to use it from classic CL/RPG apps.

New CL Commands


This CL command is a nice convenience wrapper for running SQL queries via RUNSQL and placing the results into a temporary or already existing output table in QTEMP or another library. Once a query completes, the command outputs the resulting records to the specified table. A set of data areas is also created in library QTEMP with result counts to denote how many records were returned.

A good example use case might be to call one of the Db2 services and aggregate the results into an output file for further processing.


Along with QSHPORTEND, this CL command helps manage and automate web servers and other TCP/IP services. QSHPORTCHK can check for an active TCP/IP service running on a specified IBM i port and IP address. You might have web apps and services that you’ve created and you don’t have a specific shutdown process for the app running on the port. Or maybe you just want to create a periodic service monitor job to see if your TCP services are up and running.  This command will fulfill the need for quick TCP service checks.

A good example use-case might be when you need to monitor a couple web apps or services. The first service could be a Python, PHP or Node application running on a port associated with localhost/ such as 5001. And perhaps NGINX or Apache is set up as a public web server service on port 443. Two calls to the QSHPORTCHK command can easily tell you if both of your services are up and running.


This CL command is a companion to the QSHPORTCHK command. QSHPORTEND can be used to actually end any jobs that are associated with the selected TCP port.  Both QSHPORTCHK and QSHPORTEND utilize the QSYS2.NETSTAT_JOB_INFO Db2 service to gather information on jobs that are running on the specified port. QSHPORTEND also uses the QSHQRYTMP command internally to write the results of its job search to a temporary file so the QSHPORTEND CL program can process the results.

Using our port check example above, you could first use QSHPORTCHK to check for an active TCP port and then use QSHPORTEND to end all associated jobs running on that TCP port. Think of QSHPORTEND as doing a mass ENDJOB command for all jobs running on the selected TCP port.


This command will save time for system administrators who need to set up PASE users with Bash profiles. QSHSETPROF sets up a user’s default .profile, .bash_profile and .bashrc (Qshell/PASE/bash) profile files from templates stored in source file QSHONI/SOURCE. The default templates will set up a path to the IBM-supplied open source packages located in dir: /QOpenSys/pkgs/bin. The profile template source member names are QSHPROFILE for .profile, QSHBASHPRF for .bash_profile, and QSHBASHRC for .bashrc. When you run the QSHSETPROF command and select a user profile, the command process will first attempt to create a home directory (Ex: /home/USERID) if it doesn’t already exist for the specific user profile. Then it will copy the 3 source members to create .profile, .bash_profile and .bashrsc. Once the profiles are set up, paths should be automatically set if the user runs Qshell/PASE commands via QSH or bash commands from an SSH terminal.

Make sure to visit the QShell on i GitHub site to stay up to date on QSHONI enhancements.

Verified by MonsterInsights