为什么我的Cron作业不能正常工作?

我在Ubuntu Hardy VPS上有一个cron工作,只有一半工作,我不能解决为什么。 这个工作是一个Ruby脚本,它使用mysqldump来备份由Rails应用程序使用的MySQL数据库,然后使用SFTP对其进行压缩并上传到远程服务器。

gzip文件已成功创build并复制,但始终为零字节。 但是,如果我直接从命令行运行cron命令,它的工作原理是完美的。

这是cron的工作:

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

这是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' 

我已经检查并仔细检查了所有的path,他们是正确的。 执行用户(部署)拥有sftp.yml (SFTP凭证)和database.yml (MySQL凭证),该用户拥有只读权限(chmod 400)。 我正在使用net-ssh和net-sftp的1.1.x版本。 我知道他们不是最新的,但他们是我目前熟悉的。

什么可能导致cron作业失败?

您是否确定临时文件作为cron作业运行时正确创建? 您的脚本的工作目录将在HOME环境变量中指定,或者在安装了cron作业的用户的/ etc / passwd条目中指定。 如果部署对其执行的目录没有写权限,则可以指定转储文件的绝对路径来解决该问题。

当脚本以交互方式正确运行而不是由cron运行时,问题通常是由于环境环境设置的原因…例如PATH作为@Ted Percival提到的alrady,但可能是其他环境变量。

这是因为cron在执行之前不会调用.bash_profile,.bashrc或/ etc / profile。

避免这种情况的最好方法是确保cron调用的任何脚本在执行时不会对环境做出任何假设。 为了确保环境的正确设置,可以简单地在脚本中添加几行代码。 例如,在我的情况下,我在/ etc / profile(对于RHEL)中具有所有重要的设置,因此我将在cron下运行的任何脚本中包含以下行:

 source /etc/profile 

看起来你的PATH缺少一些目录,最重要的是/bin (对于/bin/rm )。 这是我的系统的/etc/crontab使用的:

 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 

cron发送电子邮件与日志?

如果没有,请将cron的输出传输到日志文件。

确保将STDERR重定向到日志。