【问题标题】:Why Doesn't My Cron Job Work Properly?为什么我的 Cron 作业不能正常工作?
【发布时间】:2010-09-06 00:09:08
【问题描述】:

我在 Ubuntu Hardy VPS 上有一个 cron 工作,它只有一半工作,我不知道为什么。该作业是一个 Ruby 脚本,它使用 mysqldump 备份 Rails 应用程序使用的 MySQL 数据库,然后将其压缩并使用 SFTP 上传到远程服务器。

gzip 文件已成功创建和复制,但始终为零字节。但是,如果我直接从命令行运行 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'

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

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

【问题讨论】:

    标签: ruby-on-rails ruby linux ubuntu cron


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        cron 是否发送带有日志的电子邮件?

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

        确保将 STDERR 重定向到日志。

        【讨论】:

          【解决方案4】:

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

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

          避免这种情况的最佳方法是确保 cron 调用的任何脚本在执行时不对环境做出任何假设。克服这个问题可以很简单,只需在脚本中包含几行代码以确保环境设置正确。例如,在我的例子中,我在 /etc/profile(对于 RHEL)中有所有重要的设置,所以我将在任何要在 cron 下运行的脚本中包含以下行:

          source /etc/profile
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多