How to Run Cron Jobs as Specific User with Proper Environment Variables in Linux


3 views

Many developers encounter issues when trying to run cron jobs under specific user accounts. The error "command not found" typically indicates the cron environment isn't properly loading the user's PATH and other environment variables.

When you add a cron job in /etc/cron.d/ with a user specification like this:

# /etc/cron.d/myjob
* * * * * user1 /path/to/script.sh

The script executes with user1's permissions but doesn't inherit the user's full environment (like ~/.bashrc or ~/.profile settings). This is different from running the script manually as the user.

Option 1: Using su -c with Full Login Shell

The most reliable method is to use su -l to simulate a full login:

# /etc/cron.d/myjob
* * * * * root su -l user1 -c '/path/to/script.sh'

This ensures all environment variables from the user's profile are loaded.

Option 2: User's Personal Crontab

For user-specific jobs, it's often better to use the user's own crontab:

$ sudo -u user1 crontab -e

Then add the job directly:

# User user1's personal crontab
* * * * * /path/to/script.sh

Option 3: Explicitly Setting Environment

If you must use system crontab, explicitly set required environment variables:

# /etc/cron.d/myjob
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
* * * * * user1 source ~user1/.profile && /path/to/script.sh

When debugging cron issues:

  • Always use absolute paths in scripts
  • Capture stdout/stderr to log files for debugging
  • Test the environment by running env > /tmp/cronenv.log in your job
  • Consider using #!/usr/bin/env bash in scripts rather than direct paths

Here's a complete example implementing best practices:

# /etc/cron.d/backup_job
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=admin@example.com
30 2 * * * root su -l backup_user -c '/usr/local/bin/backup_script.sh >> /var/log/backup.log 2>&1'

This setup ensures:

  • Full environment loading via su -l
  • Proper path settings
  • Log capturing
  • Email notifications on failures

When setting up a cron job to run under a specific user (e.g., user1), you might encounter a "command not found" error even after specifying the user in /etc/cron.d. This typically happens because the cron job doesn't inherit the user's environment variables, including the PATH.

While /etc/cron.d allows you to specify a user in the cron entry (e.g., user1), the job still runs with a minimal environment. This means:

  • The user's .bashrc or .profile isn't sourced
  • Custom PATH settings aren't available
  • Environment variables specific to the user's session are missing

Method 1: Using crontab -e as the Target User

The most reliable way is to edit the user's personal crontab:

sudo -u user1 crontab -e

Then add your job (with full paths to commands):

0 3 * * * /usr/bin/python3 /home/user1/scripts/daily_task.py

Method 2: Using su -c in /etc/cron.d

If you must use /etc/cron.d, wrap your command with su:

0 3 * * * user1 /bin/bash -c "source /home/user1/.bashrc && /home/user1/scripts/daily_task.sh"

Method 3: Systemd Timers (Modern Alternative)

For newer systems, consider systemd timers:

[Unit]
Description=Daily task for user1

[Service]
Type=simple
User=user1
ExecStart=/home/user1/scripts/daily_task.sh

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

To troubleshoot environment problems, create a test cron job that logs the environment:

*/5 * * * * user1 /bin/bash -c "env > /tmp/cron_env.log"

Then compare with the user's normal environment:

sudo -u user1 -i env > /tmp/user_env.log
  • Always use absolute paths in cron jobs
  • Explicitly source necessary environment files if needed
  • Consider logging output for debugging
  • For complex setups, use wrapper scripts that set up the environment

Create /home/user1/scripts/run_as_user.sh:

#!/bin/bash
source /home/user1/.bashrc
export PATH=/usr/local/bin:$PATH
/home/user1/scripts/daily_task.sh >> /var/log/user1_cron.log 2>&1

Then call it from cron:

0 3 * * * user1 /bin/bash /home/user1/scripts/run_as_user.sh