You are currently on IBM Systems Media’s archival website. Click here to view our new website.


A (root) Change for the Better (part II)

In the article "A (root) Change For The Better" I explained how to create a "chroot environment.” In brief summary, chroot is a command that facilitates changing the apparent root of your current IBM i job (aka PASE process) so it thinks the current subdirectory it resides in is the root of the file system when it is not. You could think of it as being a form of a logical file system within the IFS. You can have many chroot environments limited only by disk space.

The previous article showed how to create a chroot environment from scratch by manually copying individual IFS files (binaries, text files, etc) into a new directory. That process proved to be easy enough. But what happens when the number of copied files increases by hundredfold? Manually copying and pasting commands into the PASE shell would eventually become arduous, causing you to want to automate it in some way. A logical next step would be to put all of the cp (copy) statements into a single shell script that could be called to create a chroot environment configured for a specific purpose. That's the direction I took until Tony Cairns (IBMer) introduced me to the chroot project he was working on, which is set to be delivered as a PTF in the very near future.

Side Note: Think of shell scripts being to PASE what CL is to our history—a way to automate the execution of a group of commands.

The "IBM i Chroot" (ibmichroot) project is completely open source and is hosted here on Bitbucket as a joint effort between IBM and Krengeltech. Aside from the cool aspect of a new open source project dedicated to IBM i, the ibmichroot project minimizes the labor effort involved with creating more complex chroot environments.


The first step is to obtain the ibmichroot source (shell scripts and config files) and place them in the directory /QOpenSys/ibmichroot on your IBM i. This can be done in a variety of ways. The first option is most likely the best.

  1. 1: Manually download the source from and FTP to IFS.
  2. 2: Install latest PTF for license program 5733OPS. NOTE: As of this writing (December 21, 2015), the PTF was not yet available, so I don't have any exact details.
  3. 3: Use Git to clone the repository into the IFS: git clone

Start Using It

Now it's time to create a new chroot environment. I’m going to document all of the steps and digress once they are done. First, cd (change directory) into the ibmichroot IFS directory, as shown below.

$ cd /QOpenSys/ibmichroot

Now, run the command and supply two parameters separated by spaces. The first parameter, chroot_minimal.lst, contains the configuration. The second parameter, /QOpenSys/myspace1, is the location where the chroot environment will be created.

$ chroot_minimal.lst /QOpenSys/myspace1

When you hit Enter you will see many log entries being pushed to your console showing the progress and any errors that may occur. Now that the chroot environment is created, you can enter it by running the following chroot command. The first parameter is the new chroot environment directory. The second is the command that should be run once inside the environment (in this case we want to start an interactive shell session).

$ chroot /QOpenSys/myspace1 /usr/bin/sh

Once inside the chroot environment you can run commands as you did before—except now you are limited to what you copied into the chroot environment. For example, if you need the Python runtime but didn't copy it into the chroot environment, you won't be able to see or use it. Being "limited" like this is actually a huge advantage. It means you can create extremely customized environments for different types of applications, including having different versions of software. This is great for testing new versions of Node.js, Python, PHP, Ruby, etc.

A simple way to tell if you are inside of a chroot environment is to list (ls command) the root. If you don't see /QSYS.LIB then you are most likely in a chroot environment, as shown below.

$ ls -all /
total 136
drwxr-sr-x    7 aaron    0              8192 Dec 21 21:41 .
drwxr-sr-x    7 aaron    0              8192 Dec 21 21:41 ..
drwxr-sr-x    3 aaron    0              8192 Dec 21 21:41 QOpenSys
lrwxrwxrwx    1 aaron    0                34 Dec 21 21:41 bin -> /QOpenSys/usr/bin
drwxr-sr-x    4 aaron    0              8192 Dec 21 21:41 dev
drwxr-sr-x    2 aaron    0              8192 Dec 21 21:41 home
lrwxrwxrwx    1 aaron    0                34 Dec 21 21:41 lib -> /QOpenSys/usr/lib
lrwxrwxrwx    1 aaron    0                36 Dec 21 21:41 sbin -> /QOpenSys/usr/sbin
drwxr-sr-x    2 aaron    0              8192 Dec 21 21:41 tmp
drwxr-sr-x    2 aaron    0              8192 Dec 21 21:41 usr

The reason is because /QSYS.LIB can't exist inside of chroot.

To exit out of the chroot environment, simply type the exit command.

$ exit

Then run the list (ls) command again to see /QSYS.LIB and know you are back to the actual root of the IFS.

$ ls -all /
total 246486
drwxrwsrwx   25 qsys     0            245760 Dec 11 21:43 .
drwxrwsrwx   25 qsys     0            245760 Dec 11 21:43 ..
drwx---rwx    7 qdoc     0              8192 Jan  1 1970  QDLS
drwx---rwx    2 qsys     0              2272 Nov 25 10:03 QFileSvr.400
drwxr-sr-x    7 qsys     0              8192 May 21 2015  QIBM
d------r-x    2 qdftown  0              1200 Nov 25 10:03 QNTC
drwxrwxrwx    2 qdftown  0              4096 Jan  1 1970  QOPT
drwxrwsrwx   13 qsys     0            258048 Dec 21 21:41 QOpenSys
drwx--S---    3 qsecofr  0             12288 Dec 21 07:36 QSR
drwx---r-x 1203 qsys     0          16015360 Dec 21 13:02 QSYS.LIB
drwxrws---   14 qtcp     0              8192 May 21 2015  QTCPTMM
lrwxrwxrwx    1 qsys     0                16 May 21 2015  bin -> /usr/bin
drwxrwsr-x    5 qsys     0             40960 May 21 2015  dev
drwxr-sr-x    7 qsys     0             24576 Sep 16 17:41 etc
drwxrwsrwx    5 qsys     0              8192 Nov  5 21:05 home
lrwxrwxrwx    1 qsys     0                16 May 21 2015  lib -> /usr/lib
drwxrwsrwt   17 qsys     0            114688 Dec 21 21:45 tmp
drwxr-sr-x    7 qsys     0             24576 Nov 25 09:55 usr
drwxr-sr-t    3 qsys     0              8192 May 22 2015  var
drwxrwsr-x    8 qsys     0              8192 Jul 25 03:55 www

Now, let's dig into chroot_minimal.lst to learn what happened when we ran Note I've omitted a lot of chroot_minimal.lst for the sake of brevity.

--- chroot_minimal.lst ---
/dev/tty c 32945 0
/dev/null c 32769 1
/dev/pts/0 c 32947 0
/QOpenSys/usr/sbin /sbin
/QOpenSys/usr/bin /bin
# touch /home/myuser/myfile.txt
# CHGAUT OBJ('/QOpenSys/myspace1/home/myuser') USER(myuser) DTAAUT(*RWX) OBJAUT(*ALL) SUBTREE(*ALL)

The .lst config files are made up of predefined section names prefixed with a colon (i.e., :mkdir, :mknod, :cp, :ln, :sh, :system, etc). Each section has an associated syntax that can be seen in the full version of the file on Bitbucket. For example, the :ln syntax represents the ln (link) command and requires two parameters: the source and destination. Further, the :cp section represents the cp (copy) command and only has one parameter to specify what you want copied from the base IFS to the same-named directory and file in the chroot environment. As you can see, many of the sections correlate to commonly-used actions or commands. Two are more of a catch-all for things that can't be as easily put into a black box, specifically :sh and :system. These two sections facilitate the running of any shell or 5250 command, respectively. And lastly, the # sign is used as a comment for things you don't want acted upon.

Another aspect of .lst config files is a feature called "global variables". Global variables are a simple means of doing a Find and Replace of name-value-pairs passed on the call to For example, below is a snippet of a config file named custom.lst that contains global variables myuser and mydir.

--- custom.lst ---
touch mydir/home/myuser/myfile.txt
CHGAUT OBJ('mydir/home/myuser') USER(myuser) DTAAUT(*RWX) SUBTREE(*ALL)

Below is how you specify replacement values for the global variables mydir and myuser by passing them as name-value-pairs after the first and second parameters. Note that you can call your global variables whatever you want and specify as many as you'd like. Just make sure the names on the command line and the .lst file match so the find and replace is successful.

$ custom.lst /QOpenSys/myspace1 mydir=/QOpenSys/myspace1 myuser=aaron


As you can see, the ibmichroot process can significantly reduce the labor associated with creating chroot environments. Take a look at the source on Bitbucket to see more preconfigured environments which narrow the focus to creating chroot environments specifically for Ruby, or Node.js, or PHP, etc.

So far, we've only covered how to create a chroot environment and occupy it with a few binaries that already exist on the machine. But what if we want to install Git, Nginx or Redis? I’ll be covering that in the next article as we dive into the side of ibmichroot.

Let me know if you have any questions! Comment below or shoot me an email directly at

Aaron Bartell is Director of IBM i Innovation for Krengel Technology Inc. and an IBM Champion.

Like what you just read? To receive technical tips and articles directly in your inbox twice per month, sign up for the EXTRA e-newsletter here.



2019 Solutions Edition

A Comprehensive Online Buyer's Guide to Solutions, Services and Education.

Are You Multilingual?

Rational enables development in multiplatform environments

IBM Systems Magazine Subscribe Box Read Now Link Subscribe Now Link iPad App Google Play Store
IBMi News Sign Up Today! Past News Letters