IBM Support

The Cron Environment and Cron Job Failures

Question & Answer


Question

Why does my job run from the command line but not from cron?

Answer

The Cron Environment and Cron Job Failures Introduction
What is the cron environment?
What is the current directory for a cron job?
How to extend the environment for a cron job
How to debug an environment problem in a cron job
Conclusion

Introduction

Cron is a process that reads crontab files and executes programs and scripts at the times specified in the crontab files. The programs and scripts executed by cron become child processes of cron, and thus will inherit cron's process environment. This environment consists of environment variables, a working directory, umask, resource limits, and so on. Sometimes a job executed by cron will fail, but run successfully when executed from the command line. This problem is often caused by the job's environment.

What is the cron environment?

Since the cron daemon is a system program that is started by one of the system startup scripts, its environment will not be the same as the environment inherited from the shell when a job is executed from the command line. Cron inherits its environment from its parent, which is the init process. But during cron initialization, cron can modify or extend the environment before it executes cron jobs. Generally, the default environment for a cron job will consist of /etc/environment, and the default shell environment variables such as $PATH, $HOME and $PWD. Information in /etc/profile will not be available, as well as information in ~/.profile and ~/.kshrc, so it is unlikely $PATH will  contain the same directories as it does after logging into an account. If the cron job needs any information in these shell initialization files, these scripts must be sourced at the top of the cron job script.

Another important part of the cron environment are the system limits, also known as ulimits. The ulimits for a cron job will be those that are inherited from the root account, and will likely not be the same as the ulimits for a regular user account.

Note: The at command is often used to test cron jobs. Because the at command is executed from the command line, unlike cron, it will automatically inherit the current environment of the shell.

What is the current directory for a cron job?

The current directory, which can be accessed using the shell environment variable $PWD, is set by cron to the home directory of the user who owns the crontab file. In other words, the current directory will not necessarily be the directory containing the shell script that is being executed by cron. For this reason relative paths should not be used within a script that is to be executed by cron, unless the current directory is explicitly set at the top of the script with the cd command.

How to extend the environment for a cron job

If a cron job uses aliases, environment variables, or functions that are defined in shell initialization scripts such as ~/.profile and ~/.kshrc, then these scripts can be sourced at the top of the cron job script. Of course, any additional information needed by a cron job can also be added directly at the top of the cron job script. For example, system ulimits might need to be explictly set in a cron job script.

The following example assumes a home directory has a .profile and a .kshrc file that need to be sourced in order to provide the proper environment for the cron job.

#!/bin/ksh
# The line above should contain whatever shell is required by the script below. By default,
# cron will use whatever the login shell is for the user that owns the crontab file.

# Duplicate the environment that is inherited when the script runs from the command line.
cd /home/$USER      # cron does this for us - this is here just to be safe
. /etc/profile

if [ -a .profile ]; then
   . ./.profile
fi

if [ -a .kshrc ]; then
   . ./.kshrc
fi

# Add any other required environment related information, such as system ulimits.
ulimit -d unlimited
ulimit -f 3000

# You can now change the current directory if desired.
cd /my/current/working/directory
...

How to debug an environment problem in a cron job

If a cron job script still fails after extending the cron job environment, then the script can be debugged by creating an environment variable list file from within the cron job script using the env command. This list can then be compared to a list file created when the job is executed successfully from the command line. Here is an example.

#!/bin/ksh
# The line above should contain whatever shell is required by the script below. By default,
# cron will use whatever the login shell is for the user that owns the crontab file.

# Duplicate the environment that is inherited when the script runs from the command line.
cd /home/$USER    # cron does this for us - this is here just to be safe
. /etc/profile

if [ -a .profile ]; then
   . ./.profile
fi

if [ -a .kshrc ]; then
   . ./.kshrc
fi

# Add any other required environment related information, such as system ulimits.
ulimit -d unlimited
ulimit -f 3000

# You can now change the current directory if you need to.
cd /my/current/working/directory

# Generate an environment list file.
usr/bin/env | sort > /tmp/cronEnv.out
...

Now create an environment list from the command line by running the env command under the account where the script executes successfully.

$ env | sort > /tmp/cmdLineEnv.out

Next compare the two environment list files to determine which variables need to be explicitly set in the script that is to be executed by cron. Variables that exist in the cmdLineEnv.out file but not in the cronEnv.out file should be added to the script. If a variable exists in both files but the values are different, use the value that is in the cmdLineEnv.out file.

# diff -b /tmp/cmdLineEnv.out /tmp/cronEnv.out

Finally, add export lines in the script to explicitly set whatever environment variables are required to completely duplicate the environment from the command line.

#!/bin/ksh

...

# Customize the environment still further by explicitly setting variables.
export myvar1=value
export myvar2=value
export myvar3=value
...

Conclusion

Cron job failures can often be traced to problems in the environment. Cron jobs are often tested in a particular user account with the at command, or by simply running them directly from the command line. In both cases the jobs will inherit the shell environment, but this environment will not automatically be available to a job that is executed from cron. This problem is easily resolved by modifying the cron job script to manually source shell startup scripts such as /etc/profile, ~/.profile, and ~/.kshrc, and by adding any additional environment variables, shell functions, or system resource limits that are required by the job.






[{"Product":{"code":"SWG10","label":"AIX"},"Business Unit":{"code":"BU009","label":"Systems - Server"},"Component":"Support information","Platform":[{"code":"PF002","label":"AIX"}],"Version":"5.2;5.3;6.1;7.1","Edition":""}]

Document Information

Modified date:
17 June 2018

UID

isg3T1011623