Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Doesn't My Cron Job Work Properly?

I have a cron job on an Ubuntu Hardy VPS that only half works and I can't work out why. The job is a Ruby script that uses mysqldump to back up a MySQL database used by a Rails application, which is then gzipped and uploaded to a remote server using SFTP.

The gzip file is created and copied successfully but it's always zero bytes. Yet if I run the cron command directly from the command line it works perfectly.

This is the cron job:

PATH=/usr/bin
10 3 * * * ruby /home/deploy/bin/datadump.rb

This is datadump.rb:

#!/usr/bin/ruby
require 'yaml'
require 'logger'
require 'rubygems'
require 'net/ssh'
require 'net/sftp'

APP        = '/home/deploy/apps/myapp/current'
LOGFILE    = '/home/deploy/log/data.log'
TIMESTAMP  = '%Y%m%d-%H%M'
TABLES     = 'table1 table2'

log        = Logger.new(LOGFILE, 5, 10 * 1024)
dump       = "myapp-#{Time.now.strftime(TIMESTAMP)}.sql.gz"
ftpconfig  = YAML::load(open('/home/deploy/apps/myapp/shared/config/sftp.yml'))
config     = YAML::load(open(APP + '/config/database.yml'))['production']
cmd        = "mysqldump -u #{config['username']} -p#{config['password']} -h #{config['host']} --add-drop-table --add-locks --extended-insert --lock-tables #{config['database']} #{TABLES} | gzip -cf9 > #{dump}"

log.info 'Getting ready to create a backup'
`#{cmd}`    

# Strongspace
log.info 'Backup created, starting the transfer to Strongspace'
Net::SSH.start(ftpconfig['strongspace']['host'], ftpconfig['strongspace']['username'], ftpconfig['strongspace']['password']) do |ssh|
  ssh.sftp.connect do |sftp|
    sftp.open_handle("#{ftpconfig['strongspace']['dir']}/#{dump}", 'w') do |handle|
      sftp.write(handle, open("#{dump}").read)
    end
  end
end
log.info 'Finished transferring backup to Strongspace'

log.info 'Removing local file'
cmd       = "rm -f #{dump}" 
log.debug "Executing: #{cmd}"
`#{cmd}`
log.info 'Local file removed'

I've checked and double-checked all the paths and they're correct. Both sftp.yml (SFTP credentials) and database.yml (MySQL credentials) are owned by the executing user (deploy) with read-only permissions for that user (chmod 400). I'm using the 1.1.x versions of net-ssh and net-sftp. I know they're not the latest, but they're what I'm familiar with at the moment.

What could be causing the cron job to fail?

like image 805
John Topley Avatar asked Aug 16 '08 16:08

John Topley


People also ask

Why cron job is not working?

Check permissionsAnother user might have created the cron job and you may not be authorized to execute it. Note that the root must own jobs added as files in a /etc/cron. */ directory. That means that if you don't have root permissions, you might not be able to access the job.

What does 0 * * * * mean in crontab?

0 * * * * -this means the cron will run always when the minutes are 0 (so hourly) 0 1 * * * - this means the cron will run always at 1 o'clock. * 1 * * * - this means the cron will run each minute when the hour is 1.

How do you handle a cron job failure?

Create a some kind of scheduler where you can write your CRON job again if it fails, in this case you will need one more CRON job to read you scheduler and run proper command. Scheduler can be database / file / NoSQL based.


2 Answers

When scripts run correctly interactively but not when run by cron, the problem is usually because of the environment environment settings in place ... for example the PATH as alrady mentioned by @Ted Percival, but may be other environment variables.

This is because cron will not invoke .bash_profile, .bashrc or /etc/profile before executing.

The best way to avoid this is to ensure any scripts invoked by cron do not make any assumptions about the environment when executing. Over-coming this can be as simple as including a few lines in your script to make sure the environment is setup properly. For example, in my case I have all the significant settings in /etc/profile (for RHEL), so I will include the following line in any scripts to be run under cron:

source /etc/profile
like image 101
tardate Avatar answered Nov 05 '22 03:11

tardate


Looks like your PATH is missing a few directories, most importantly /bin (for /bin/rm). Here's what my system's /etc/crontab uses:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
like image 34
Ted Percival Avatar answered Nov 05 '22 03:11

Ted Percival