Libraries, objects, library list, IFS and jobs: the IBM i mental model web developers lack
When I first sat in front of a 5250 screen, I kept looking for a file tree. There isn't one in the place where most of your work lives. IBM i is object-based, not file-based, and almost every confusing moment for a web developer comes from that one difference.
This article maps each IBM i concept to its nearest Linux or web equivalent. The maps are approximate. I'll flag where they break.
The big picture in one table
| IBM i | Nearest Linux / web idea | Where the analogy breaks |
|---|---|---|
Library (*LIB) |
A flat directory / schema | Libraries can't nest. One level only. |
| Object | A typed file | The OS knows the type and enforces what you can do with it. |
| Library list |
$PATH plus a search path for everything |
It resolves data files and programs, not just executables. |
| IFS | Ordinary POSIX filesystem | Lives alongside the library system, not instead of it. |
| Job | A process with its own environment | Carries its own library list, user, and message log. |
| Subsystem | A systemd slice / worker pool config | Defines memory pools and job routing. |
| Job log | stderr plus an audit trail per process | Kept per job, queryable after it ends. |
Libraries and objects
A library is a container of objects. Think "schema" more than "folder". You can't put a library inside a library, so names carry meaning: PAYROLL, PAYROLLDEV, QGPL.
An object has a name, a library, and a type. The type decides which commands work on it. You don't "open" a program the way you open a file; you CALL it.
The types you'll meet in the first month:
| Type | What it is | Web/Linux analogue |
|---|---|---|
*PGM |
Compiled program | A compiled binary |
*SRVPGM |
Service program: shared procedures | A shared library (.so) |
*FILE |
Database table, view, source file, display file, printer file | A table, plus UI and print definitions |
*DTAARA |
Data area: one small value, like a config flag or counter | A single-row config table or env var |
*MSGQ |
Message queue | A mailbox / log destination you can read and reply to |
*JOBQ |
Job queue: batch jobs waiting to run | A work queue (think Sidekiq or a cron backlog) |
*OUTQ |
Output queue: holds spooled output | A print spool |
Notice that *FILE covers a lot. A DB2 table is a *FILE of attribute PF. A source member lives in a *FILE of attribute PF-SRC. Same type, different use.
Fully qualified, an object is LIBRARY/OBJECT, for example MYLIB/CUSTMAST. Try it:
WRKOBJ OBJ(MYLIB/*ALL) OBJTYPE(*ALL)
That lists every object in MYLIB with its type. It's the closest thing to ls -l.
QSYS.LIB versus the IFS
There are really two filesystems.
- QSYS.LIB: the native library system. Objects, libraries, members. Names are limited and traditionally uppercase.
-
IFS (Integrated File System): a normal hierarchical tree under
/, with/home/YOURUSER, stream files, and permissions. It is POSIX-like and case-sensitive in the/rootfile system.
The two are connected. The IFS exposes libraries as a path:
/QSYS.LIB/MYLIB.LIB/CUSTMAST.FILE
That's the same object as MYLIB/CUSTMAST, seen through the IFS. Git, Node.js, Python, and your .profile all live in the IFS side. RPG programs and database tables live on the QSYS.LIB side.
Library list resolution
You almost never write MYLIB/CUSTMAST in real code. You write CUSTMAST and the system finds it by walking the library list.
DSPLIBL
The list has four parts, searched in this order:
-
System portion: IBM libraries like
QSYS,QSYS2. - Product portion: libraries added by licensed products.
- Current library: a single library, where new objects get created by default.
- User portion: your own libraries.
The first match wins. If two libraries both contain a program called CALCTAX, whichever comes first in the list runs. This is $PATH behavior, with the same bugs: "works in test, breaks in prod" is very often a different library list.
Change it for your job:
ADDLIBLE LIB(MYLIB)
CHGCURLIB CURLIB(MYLIB)
These affect only the current job. Other users keep their own lists.
Jobs, subsystems and job logs
Everything that runs is a job. Your 5250 sign-on is a job. A nightly batch run is a job. A web server request through an IBM i service can be a job too.
A job has:
- a user profile and its authorities,
- its own library list,
- its own job log,
- a place it runs, a subsystem.
A subsystem is a runtime environment. QINTER handles interactive sessions, QBATCH runs batch work from job queues, QUSRWRK hosts a lot of server jobs. A subsystem defines the memory pool and how jobs are routed in.
To see what's running:
WRKACTJOB
You'll see columns for subsystem, user, job type, CPU, and status (RUN, MSGW for waiting on a message, DEQW for waiting on a queue). MSGW is the one to learn first. It means the job stopped and asked a human a question.
When a job fails, the job log tells you why. It's the first place I look.
DSPJOBLOG
Run it right after a failed command in your own session. To find another job's log, use WRKACTJOB, take option 5 on the job, then option 10 to display the job log.
Submitting batch work and finding its output:
SBMJOB CMD(CALL PGM(MYLIB/NIGHTLY)) JOB(NIGHTLY) JOBQ(QBATCH)
WRKSPLF
SBMJOB puts the command on a job queue. Printed output and job logs end up as spooled files in an output queue. WRKSPLF lists yours. It's the equivalent of looking in a log directory, except the OS manages the files.
Where source code lives
This trips up web developers hardest. Traditionally, RPG source is not a file. It is a member inside a source physical file:
MYLIB/QRPGLESRC(HELLO) reads as library / source file / member:
- Library MYLIB: The container
- Source file QRPGLESRC: A *FILE object that holds source members
- Member HELLO: One piece of source inside the source file
-
QRPGLESRCholds RPG source members,QCLSRCholds CL source,QDDSSRCholds DDS. - Records are fixed length (often 112 characters: 12 for sequence and date, 100 for text). That's one reason older RPG is column-bound.
- You edit with
STRSEU(old), RDi, or VS Code with Code for IBM i.
Modern practice puts source in the IFS as ordinary .rpgle, .clle, .sqlrpgle files, tracked in Git, and compiles from there using the SRCSTMF parameter. New projects should do this. Most legacy shops still keep source in source PFs, and you will have to read both.
A quick check of how many members exist in a source file:
SELECT SYSTEM_TABLE_MEMBER, LAST_SOURCE_UPDATE_TIMESTAMP
FROM QSYS2.SYSPARTITIONSTAT
WHERE SYSTEM_TABLE_SCHEMA = 'MYLIB'
AND SYSTEM_TABLE_NAME = 'QRPGLESRC';
This model underpins everything else: the roadmap puts it at stage 1, and AS400 vs iSeries vs IBM i covers the platform naming. Job logs and SBMJOB get a full treatment in CL programming essentials, and service programs (*SRVPGM) are explained in ILE modules, service programs and the binder.
Try it on PUB400
If you haven't got an account yet, start with Your free IBM i lab in 30 minutes: PUB400 + VS Code + Code for IBM i. Then, signed on to PUB400 in a 5250 session:
- Run
DSPLIBLand note what's in the user portion. - Run
WRKOBJ OBJ(YOURUSERLIB/*ALL) OBJTYPE(*ALL)(PUB400 creates a personal library for your user; checkDSPLIBLorWRKLIBfor its exact name) and identify which entries are*FILE,*PGM,*DTAARA. - Create a data area and read it back:
CRTDTAARA DTAARA(YOURUSERLIB/MYFLAG) TYPE(*CHAR) LEN(10) VALUE('HELLO')
DSPDTAARA DTAARA(YOURUSERLIB/MYFLAG)
- Run
WRKACTJOB, find your own interactive job, and press5then10to see its job log. - In a terminal or VS Code, list
/home/YOURUSERin the IFS and compare it to your library.
Resource limits on PUB400 are shared and some commands are restricted, so if one fails, read the message rather than assuming you broke it. DSPJOBLOG will tell you which authority was missing.
Best resources
- IBM Docs, IBM i documentation: authoritative reference for every command and object type; search by command name
- Code for IBM i docs: setting up VS Code, the Object Browser and IFS Browser to see both filesystems side by side
- Barrett Otte, IBMi-Book: a free community-written book covering the system from a developer's angle
- RPGPGM.com: Simon Hutchinson's long-running blog with practical IBM i and RPG how-tos
- PUB400: free public IBM i to practice every command above
Next
Your first free-format RPG program
Related
- Free IBM i lab: PUB400 + VS Code
- CL programming essentials
- ILE modules, service programs and the binder
Originally published on rainierio.dev. The full Learn IBM i track, with an Indonesian version, is at rainierio.dev/learn.
Top comments (0)