我在Ubuntu Hardy VPS上做了一份计划工作,只有一半可以工作,我不知道为什么。 该工作是一个Ruby脚本,它使用mysqldump备份Rails应用程序使用的MySQL数据库,然后将其压缩并使用SFTP上传到远程服务器。
gzip文件已成功创建并复制,但始终为零字节。 但是,如果我直接从命令行运行cron命令,它将运行完美。
这是cron工作:
1 2
| PATH=/usr/bin
10 3 * * * ruby /home/deploy/bin/datadump.rb |
这是datadump.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #!/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)。 我正在使用net-ssh和net-sftp的1.1.x版本。 我知道它们不是最新的,但是它们是我目前所熟悉的。
是什么导致cron作业失败?
如果脚本可以交互地正确运行,但不能由cron运行,则问题通常是由于环境环境设置适当,例如@Ted Percival提到的PATH路径,但可能是其他环境变量。
这是因为cron在执行之前不会调用.bash_profile,.bashrc或/ etc / profile。
避免这种情况的最佳方法是确保cron调用的任何脚本在执行时都不会对环境做出任何假设。克服这一难题很简单,只需在脚本中包含几行内容即可确保正确设置了环境。例如,就我而言,我在/ etc / profile中具有所有重要的设置(对于RHEL),因此我将在要在cron下运行的任何脚本中包括以下行:
看起来您的PATH缺少一些目录,最重要的是/bin(对于/bin/rm)。这是我系统的/etc/crontab所使用的:
1
| PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin |
作为cron作业运行时,您确定临时文件创建正确吗?脚本的工作目录将在HOME环境变量中指定,或者在安装cron作业的用户的/ etc / passwd条目中指定。如果deploy对执行目录没有写权限,则可以为转储文件指定绝对路径以解决此问题。
cron是否发送带有日志的电子邮件?
如果不是,则将cron的输出通过管道传输到日志文件。
确保将STDERR重定向到日志。