The previous post covered the modern IBM i developer workstation — VS Code with the Code for IBM i extension, IBM Merlin, Git integration with IFS stream files, custom compile actions, Bob for automated builds, and GitHub Copilot and watsonx Code Assistant for RPG and CL source editing. This post covers the IBM i PASE runtime in depth: what PASE is, how it differs from QShell, AIX binary compatibility, environment variable handling, PASE process management, shared library loading, yum package management, and how PASE integrates with the IBM i job structure and ILE activation groups in 2026.
What Is PASE?
PASE (Portable Application Solutions Environment) is a runtime environment built into IBM i that provides an AIX-compatible execution layer on top of the IBM i operating system. PASE allows AIX and Linux binaries — compiled for the PowerPC architecture — to run directly on IBM i without recompilation. It ships as part of 5770-SS1 option 33 (PASE for i) and is installed on most modern IBM i systems.
PASE is not a virtual machine and it is not emulation. It is a true operating system personality layer — PASE processes run natively on the IBM i POWER processor alongside ILE programs, sharing the same hardware resources. A PASE process has a full POSIX process environment: file descriptors, signals, environment variables, a stack, and a heap. From the PASE process perspective, the system looks like AIX 7.1.
PASE is what makes the IBM i open-source ecosystem possible. Node.js, Python, Ruby, PHP, Perl, Git, curl, yum, and hundreds of other open-source tools run on IBM i because they are either compiled AIX binaries or open-source software compiled for PASE using the IBM i open-source build infrastructure maintained by the IBM i Open Source team.
PASE vs QShell (QSH)
IBM i provides two POSIX-like shell environments: PASE and QShell. They serve different purposes and have important differences:
| Feature | PASE | QShell (QSH) |
|---|---|---|
| Shell binary | bash, ksh, sh (AIX shells) | qsh (IBM’s Korn shell variant) |
| Binary compatibility | AIX/PASE binaries (.so, executables) | Only QShell built-in commands and ILE programs via qsh |
| Open-source tools | Full open-source ecosystem via yum | Limited — only what IBM ships |
| Process model | POSIX fork/exec; full signal support | Runs inside an IBM i ILE job |
| Start from CL | CALL QSYS/QP2SHELL or QP2TERM | STRQSH or QSH command |
| Environment variables | Inherited POSIX env vars; full PATH | Limited environment variable support |
| Use case | Running open-source tools, scripts, servers | Simple IBM i shell scripting, IFS file operations |
For any serious scripting, open-source use, or running Node.js and Python, use PASE. QShell is useful for simple IFS operations and calling IBM i commands from a shell context, but it cannot run PASE binaries.
Starting a PASE Session
There are several ways to start a PASE environment:
SSH — the most common method for interactive and automated PASE sessions. When a user SSHs into IBM i, the SSH daemon (SSHD) starts a PASE shell process. The default shell is bash if bash is installed:
# From a developer's workstation ssh devuser@my-ibm-i.company.com # The SSH daemon starts a bash session in PASE
CALL QP2TERM — starts an interactive PASE terminal session from a 5250 green-screen job. The terminal runs in the current IBM i job’s PASE layer:
/* From a CL command line or 5250 session */ CALL QP2TERM /* Opens a PASE ksh session in the 5250 window */
QP2SHELL / QP2SHELL2 — runs a single PASE command from a CL program or SBMJOB without an interactive session:
/* Run a PASE shell command from CL */
CALL PGM(QP2SHELL) PARM('/QOpenSys/usr/bin/bash'
'-c'
'cd /home/devuser/project && git pull')
/* QP2SHELL2 — uses the PASE environment of the calling job */
CALL PGM(QP2SHELL2) PARM('/QOpenSys/usr/bin/python3'
'/home/scripts/process_orders.py')
STRPASE (PASE terminal) — a legacy method that opens a full PASE terminal in a 5250 window. Similar to QP2TERM. Less commonly used since SSH became standard.
AIX Binary Compatibility
PASE implements a compatibility layer for AIX 7.1 on POWER. This means that a binary compiled on AIX 7.1 for POWER (64-bit or 32-bit) can be copied to IBM i and run in PASE without modification, provided all shared library dependencies are satisfied.
The compatibility includes:
- System calls — POSIX system calls (open, read, write, fork, exec, mmap, socket, etc.) are implemented in PASE and map to IBM i equivalents
- C runtime library — libc.a / libc.so (the AIX C library) is provided by PASE
- POSIX threads (pthreads) — libpthreads.a is available; PASE threads map to IBM i threads within the PASE job
- Berkeley sockets — TCP/IP socket programming works identically to AIX; the IBM i TCP/IP stack is used underneath
- Signals — SIGTERM, SIGKILL, SIGHUP, SIGUSR1, etc. are supported
What PASE does not support from AIX:
- AIX kernel extensions (LKMs)
- SMIT (AIX system management interface)
- AIX-specific subsystems like SRC (System Resource Controller)
- Direct access to IBM i objects outside of the IFS — PASE sees the IFS as its filesystem root
Environment Variables in PASE
PASE maintains its own environment variable space, separate from IBM i job-level environment variables (set with ADDENVVAR/CHGENVVAR in CL). Environment variables set in a CL job do not automatically appear in a PASE process started from that job — and vice versa.
The critical PASE environment variables:
# View current PASE environment in a bash session env # Key variables explained: PATH=/QOpenSys/pkgs/bin:/QOpenSys/usr/bin:/usr/bin # Determines where bash looks for executables # /QOpenSys/pkgs/bin is where yum-installed tools go (Node.js, Python, git, etc.) # /QOpenSys/usr/bin is the base AIX PASE utilities HOME=/home/devuser # Home directory in the IFS LIBPATH=/QOpenSys/pkgs/lib:/QOpenSys/usr/lib # Shared library search path (AIX uses LIBPATH, not LD_LIBRARY_PATH) # Note: IBM i PASE uses LIBPATH (like AIX), not LD_LIBRARY_PATH (like Linux) JAVA_HOME=/QOpenSys/QIBM/ProdData/JavaVM/jdk80/64bit # JDK location if Java is needed QIBM_MULTI_THREADED=Y # Required for some PASE tools that need multi-threading to work correctly
Setting PASE environment variables persistently for a user’s SSH sessions requires adding export statements to the user’s PASE profile files:
# /home/devuser/.bash_profile — runs on interactive login export PATH=/QOpenSys/pkgs/bin:/QOpenSys/usr/bin:$PATH export LIBPATH=/QOpenSys/pkgs/lib:/QOpenSys/usr/lib:$LIBPATH export NODE_ENV=production export DB_HOST=my-ibm-i.company.com # /home/devuser/.bashrc — runs for every bash shell alias ll='ls -la' alias gs='git status'
For PASE processes started from CL via QP2SHELL, pass environment variables explicitly using the ADDENVVAR CL command before calling QP2SHELL, or construct the environment in the shell script itself:
/* Set PASE environment vars from CL before calling QP2SHELL */
ADDENVVAR ENVVAR(NODE_ENV) VALUE(production) REPLACE(*YES)
ADDENVVAR ENVVAR(APP_PORT) VALUE(3000) REPLACE(*YES)
CALL PGM(QP2SHELL) PARM('/QOpenSys/pkgs/bin/node'
'/home/app/server.js')
PASE Process Management
PASE processes are standard POSIX processes. In a PASE bash session, standard Unix process management tools work as expected:
# List all PASE processes for the current user ps -ef | grep devuser # List all PASE processes system-wide ps -ef # Example output: # UID PID PPID C STIME TTY TIME CMD # devuser 1234 1 0 08:01 pts/0 00:00:00 bash # devuser 1235 1234 0 08:01 pts/0 00:00:02 node /home/app/server.js # devuser 1236 1234 0 08:02 pts/0 00:00:00 ps -ef # Send a signal to a PASE process kill -SIGTERM 1235 # Graceful shutdown request kill -SIGKILL 1235 # Force kill # Run a process in the background, detached from the terminal nohup node /home/app/server.js > /home/app/server.log 2>&1 & # View background jobs in the current shell jobs -l
From IBM i CL, PASE processes appear as IBM i jobs in WRKACTJOB. They show with a job type of ASJ (Asynchronous Job) or as part of the QBATCH or QSYSWRK subsystems depending on how they were started. Use WRKACTJOB SBS(*ALL) to see them, or:
/* From a CL command line — find active PASE jobs */ WRKACTJOB SBS(QSYSWRK) OUTPUT(*PRINT) /* Look for jobs with PGM of QP2SHELL or with a PASE-related job name */
To end a PASE process from IBM i CL (when you cannot SSH in), find the job name in WRKACTJOB and use ENDJOB:
/* End a PASE job cleanly from CL */ ENDJOB JOB(123456/DEVUSER/QPADEV0001) OPTION(*CNTRLD) DELAY(30)
Shared Libraries in PASE
PASE uses the AIX shared library model. Shared libraries have the extension .a (archive, containing shared members) or .so (shared object, Linux-style naming used by newer packages). The library search path is controlled by the LIBPATH environment variable (not LD_LIBRARY_PATH as on Linux — a common source of confusion).
# Check which shared libraries a PASE binary depends on dump -X64 -H /QOpenSys/pkgs/bin/node | grep NEEDED # Example output: # [0] NEEDED libpthreads.a(shr_xpg5_64.o) # [1] NEEDED libc.a(shr_64.o) # [2] NEEDED libdl.a(shr_64.o) # Check the current LIBPATH echo $LIBPATH # Add a custom library path for a session export LIBPATH=/home/devuser/mylib:$LIBPATH # Or pass it inline for a single command LIBPATH=/home/devuser/mylib:/QOpenSys/pkgs/lib node server.js
The IBM i open-source packages installed via yum place their shared libraries in /QOpenSys/pkgs/lib. This directory must be in LIBPATH for yum-installed tools to find their dependencies. If you see errors like Could not load program ... : No such file or directory, it almost always means a missing LIBPATH entry.
yum Package Management
Since IBM i 7.3 TR7 (and 7.4+), the IBM i open-source team provides a yum-based package manager for PASE. Hundreds of packages are available in the IBM i open-source RPM repository: Node.js, Python 3, git, curl, wget, OpenSSL, SQLite, nginx, and many more.
# Bootstrap yum (first-time setup if ACS bootstrap was not used) # Download bootstrap from: https://public.dhe.ibm.com/software/ibmi/products/pase/rpms/bootstrap.sh /QOpenSys/usr/bin/bash bootstrap.sh # Update the package index yum update # Search for a package yum search nodejs # Install a package yum install nodejs20 # Install Python 3 yum install python39 python39-pip # List installed packages yum list installed # Remove a package yum remove nodejs18 # Show package details yum info git
All yum-installed packages go into /QOpenSys/pkgs/. Binaries are in /QOpenSys/pkgs/bin, libraries in /QOpenSys/pkgs/lib, and headers in /QOpenSys/pkgs/include. Always include /QOpenSys/pkgs/bin at the front of PATH so yum-installed tools take precedence over the older base PASE tools in /QOpenSys/usr/bin.
PASE and ILE Integration
PASE and ILE run in the same IBM i job. A PASE process and an ILE program can share the same job and communicate through several mechanisms:
Data queues and message queues — an ILE RPG program can write to a data queue that a PASE Python or Node.js script reads, and vice versa. This is the most common integration pattern for decoupling ILE batch from PASE-based event processing.
DB2 for i (shared database) — both PASE and ILE programs connect to the same DB2 for i database. A PASE Python script can insert rows that an RPG program reads, or an RPG program can update a status column that a Node.js process monitors.
IFS stream files — ILE programs can write to IFS stream files using the QSYS2.IFS_WRITE_UTF8 SQL function or the open()/write() IFS APIs; PASE processes read those files. Similarly, PASE scripts write output files that ILE programs consume.
Sockets — a PASE server (Node.js REST API, Python socket server) and an ILE RPG client can communicate over TCP/IP loopback sockets. The RPG program calls the PASE server using IBM i socket APIs or HTTPAPI.
PASE service programs called from ILE — advanced use case: a PASE shared library (.so) can be called from ILE C or RPG using the ILECALLABLE wrapper. This allows using AIX C libraries from ILE programs.
/* Call a PASE script from CL and wait for it to complete */
CALL PGM(QP2SHELL) PARM('/QOpenSys/pkgs/bin/python3'
'/home/scripts/sync_customers.py'
'--env=production')
/* The CL program waits until the Python script exits */
/* Check the job log for any output the script printed to stdout/stderr */
PASE processes started from CL via QP2SHELL run inside the calling IBM i job’s PASE environment. They share the same job name and authority. PASE processes started via SSH get their own IBM i job, created by the SSHD daemon.
Next post: RPG Data Structures in Depth — dcl-ds syntax, qualified data structures with dot notation, LIKEDS for cloning a structure, template data structures, data structure arrays, external DB2 data structures using EXTNAME and LIKEREC, nested data structures, and passing DS to subprocedures by reference and by value.