When cron jobs fail with exit status 127, it typically indicates one of three scenarios:
1. The command interpreter cannot find the specified executable
2. Required environment variables (especially PATH) aren't properly set
3. Permission issues prevent command execution
Cron executes commands in a minimal environment that differs significantly from your interactive shell. Key differences include:
- Limited PATH (often just /usr/bin:/bin)
- No shell initialization files (.bashrc, .bash_profile) loaded
- Different working directory (usually user's home directory)
To identify the exact failure point, modify your cron job to capture debugging information:
*/10 * * * * cd /home/deploy/apps/dashboard/current && \
env > /tmp/cron_env.log 2>&1 && \
which bundle >> /tmp/cron_debug.log 2>&1 && \
bundle exec rake some:task >> /tmp/cron_output.log 2>&1
Option 1: Full Path Specification
*/10 * * * * cd /home/deploy/apps/dashboard/current && \
/usr/local/bin/bundle exec /usr/local/bin/rake some:task
Option 2: Setting Environment in Crontab
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/10 * * * * cd /home/deploy/apps/dashboard/current && \
bundle exec rake some:task
Option 3: Wrapper Script Approach
Create /home/deploy/run_rake.sh:
#!/bin/bash -l
source ~/.bashrc
cd /home/deploy/apps/dashboard/current
bundle exec rake some:task
Then in crontab:
*/10 * * * * /bin/bash -l /home/deploy/run_rake.sh
For complex Ruby/Rails environments, consider these additional measures:
# In crontab
RAILS_ENV=production
GEM_HOME=/home/deploy/.gem/ruby/2.7.0
BUNDLE_PATH=/home/deploy/.gem/ruby/2.7.0
*/10 * * * * cd /home/deploy/apps/dashboard/current && \
/usr/local/bin/bundle exec /usr/local/bin/rake some:task
After making changes, monitor system logs to confirm successful execution:
# View cron-specific logs
grep CRON /var/log/syslog
# Alternative for systems using journalctl
journalctl -u cron --since "1 hour ago"
When cron reports exit status 127, it typically means the shell couldn't find the specified command. Unlike your interactive shell session, cron jobs run with a minimal environment that often lacks crucial PATH variables.
# Example of what you might see in syslog
Jun 7 05:10:01 server CRON[15664]: (deploy) CMD (cd /home/deploy/apps/dashboard/current && bundle exec rake some:task
Jun 7 05:10:01 server CRON[15662]: (CRON) error (grandchild #15664 failed with exit status 127)
To diagnose PATH-related cron issues, try these debugging commands:
# Check your current PATH in interactive shell
echo $PATH
# Compare with cron's PATH by creating a test job
* * * * * /usr/bin/env > /tmp/cronenv.log
For robust Rails cron jobs, consider this approach that handles PATH, Ruby environment, and proper working directory:
# In your crontab -e
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/10 * * * * cd /home/deploy/apps/dashboard/current && \
/bin/bash -lc 'source /home/deploy/.bash_profile && \
bundle exec rake some:task RAILS_ENV=production >> log/cron.log 2>&1'
For complex setups, consider these options:
# Option 1: Wrapper script
#!/bin/bash
source /home/deploy/.bashrc
cd /home/deploy/apps/dashboard/current
bundle exec rake some:task
# Option 2: RVM/cron integration
rvm cron setup
rvm use 2.7.0@dashboard --create
- Always capture output using >> logfile 2>&1
- Test commands manually using sudo -u deploy -i to simulate cron's environment
- Check mail (usually /var/mail/$USER) for cron error messages
- Verify file permissions on all executables (bundle, rake, ruby)
Here's a comprehensive solution for a Rails 6 app with RVM:
# In /etc/cron.d/rails_app
SHELL=/bin/bash
PATH=/usr/local/rvm/gems/ruby-2.7.0/bin:/usr/local/rvm/gems/ruby-2.7.0@global/bin:/usr/local/rvm/rubies/ruby-2.7.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/rvm/bin
*/5 * * * * deploy /bin/bash -lc 'cd /home/deploy/apps/production/current && RAILS_ENV=production bundle exec rake maintenance:daily --silent >> log/cron.log 2>&1'