2014-03-03 153 views
4

我有一个应该在特定时间每天运行的django脚本。我正在尝试使用crontab来实现此目的。脚本应该转储数据库,使用gzip进行归档并将其上传到bitbucketCron没有运行django命令

以下是我crontab文件的相关部分:

00 4 * * * root python /my_django_project_path/manage.py update_locations 
47 16 * * * root python /my_django_project_path/manage.py database_bu 

当我执行python /my_django_project_path/manage.py database_bu它完美的罚款。然而,crontab或者不执行它,或者一路上发生的事情。即使是更奇怪的,第一个crontab命令(update_locations)也可以很好地执行。

阅读this question,我曾尝试以下,没有成功:

更改命令:

47 16 * * * root (cd /my_django_project_path/ && python manage.py database_bu) 

更改命令:

47 16 * * * root /usr/bin/python /my_django_project_path/manage.py database_bu 

添加以下以我的脚本(即使没有它的另一个工作正常):

#!/usr/bin/python 

from django.core.management import setup_environ 
import settings 
setup_environ(settings) 

通过出口Django的项目设置的脚本运行的一切:

/my_django_project_path/cron_command_executor.sh:

export DJANGO_SETTINGS_MODULE=my_django_project.settings 
python manage.py ${*} 

crontab中的以下内容:

47 16 * * * root ./my_django_project_path/cron_command_executor.sh database_bu 

将用户更改为我的用户和Apache用户(www-data)。

我在我的crontab文件的最后有一个换行符。

UPDATE:

在做sudo su,运行命令手动不再起作用。它卡住了,什么都不做。

tail -f /var/log/syslog输出是:

Mar 3 18:26:01 my-ip-address cron[726]: (system) RELOAD (/etc/crontab) 
Mar 3 18:26:01 my-ip-address CRON[1184]: (root) CMD (python /my_django_project_path/manage.py database_bu) 

UPDATE:

我使用下面的.netrc文件,以防止git的要求凭据:

machine bitbucket.org 
    login myusername 
    password mypassword 

的实际代码备份脚本是:

import subprocess 
import sh 
import datetime 
import gzip 
from django.core.management.base import BaseCommand 

class Command(BaseCommand): 
    def handle(self, *args, **options): 
     execute_backup() 

FILE_NAME = 'some_file_name.sql' 
ARCHIVE_NAME = 'some_archive_name.gz' 
REPO_NAME = 'some_repo_name' 
GIT_USER = 'some_git_username' # You'll need to change this in .netrc as well. 
MYSQL_USER = 'some_mysql_user' 
MYSQL_PASS = 'some_mysql_pass' 
DATABASE_TO_DUMP = 'SomeDatabase' # You can use --all-databases but be careful with it! It will dump everything!. 

def dump_dbs_to_gzip(): 
    # Dump arguments. 
    args = [ 
     'mysqldump', '-u', MYSQL_USER, '-p%s' % (MYSQL_PASS), 
     '--add-drop-database', 
     DATABASE_TO_DUMP, 
    ] 
    # Dump to file. 
    dump_file = open(FILE_NAME, 'w') 
    mysqldump_process = subprocess.Popen(args, stdout=dump_file) 
    retcode = mysqldump_process.wait() 
    dump_file.close() 
    if retcode > 0: 
     print 'Back-up error' 
    # Compress. 
    sql_file = open(FILE_NAME, 'r') 
    gz_file = gzip.open(ARCHIVE_NAME, 'wb') 
    gz_file.writelines(sql_file) 
    gz_file.close() 
    sql_file.close() 
    # Delete the original file. 
    sh.rm('-f', FILE_NAME) 

def clone_repo(): 
    # Set the repository location. 
    repo_origin = 'https://%[email protected]/%s/%s.git' % (GIT_USER, GIT_USER, REPO_NAME) 

    # Clone the repository in the /tmp folder. 
    sh.cd('/tmp') 
    sh.rm('-rf', REPO_NAME) 
    sh.git.clone(repo_origin) 
    sh.cd(REPO_NAME) 

def commit_and_push(): 
    # Commit and push. 
    sh.git.add('.') 
    sh.git.commit(m=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) 
    sh.git.push('origin', 'master') 
    sh.cd('..') 
    sh.rm('-rf', REPO_NAME) 

def execute_backup(): 
    clone_repo() 
    dump_dbs_to_gzip() 
    commit_and_push() 

if __name__ == "__main__": 
    execute_backup() 

UPDATE:

我设法用Chris Clark's suggestion of calling the script directly rather than through manage.py修复它。但是,我仍然对造成这个问题的原因感兴趣,所以赏金仍然可用。

UPDATE [解决]:

添加以下行/etc/environment并运行它作为我的用户帐户,而不是根固定它:

PWD=/my_django_project_path/helpers/management/commands 

我仍然不知道为什么只有我的用户可以运行如果有人有解决方案,请捐助。

+0

你可以'tail -f/var/log/syslog'来查看是否有CRON错误? – jperelli

+0

如果你为''su'执行命令并尝试运行它,会发生什么? –

+0

@jperelli,这与crontab有关:Mar 3 18:26:01 my-ip-address cron [726]:(* system *)RELOAD(/ etc/crontab) Mar 3 18:26:01 my-ip - 地址CRON [1184]:(根)CMD(python /my_django_project_path/manage.py database_bu) –

回答

2

由于一些版本的python /my_django_project_path/manage.py database_bu为你的作品,这意味着该问题是在你cron environment,或在路上,你已经设置了cron和不与脚本本身(如文件的大小要上传或网络连接不会造成问题)。

首先,你所运行的脚本

47 16 * * *根蟒蛇/my_django_project_path/manage.py database_bu

您提供其用户名root,这是不与当前用户相同的用户,而shell命令适用于当前用户。使用sudo suroot用户没有运行相同命令的事实表明您的root用户帐户无论如何都没有正确配置。 FWIW,以root身份安排某些事情几乎总是可以避免的,因为它会导致文件权限问题。

因此,请尝试从当前用户调度您的cron作业,如下所示。

47 16 * * * cd /my_django_project_path/ && python manage.py database_bu 

这可能仍然不能完全运行cron作业。在这种情况下,问题可能出现在2个地方 - 您的shell环境中有一些变量从cron环境中丢失,或者您的.netrc文件没有被正确读取,或者两者都没有被正确读取。

根据我的经验,我发现,PATH变量会导致最烦恼,让你的shell中运行echo $PATH,如果你得到的路径值是/some/path:/some/other/path:/more/path/values,运行cron作业一样

47 16 * * * export PATH="/some/path:/some/other/path:/more/path/values" && cd /my_django_project_path/ && python manage.py database_bu 

如果这不工作,接下来检查所有的环境变量。

使用printenv > ~/environment.txt从一个正常的shell中获取shell中设置的所有环境变量。然后使用以下cron条目* * * * * printenv > ~/cron_environment.txt来识别cron环境中缺少的变量。另外,您也可以使用该代码段的脚本从该脚本

import os 
os.system("printenv") 

得到环境的价值两者进行比较,找出任何其他相关变量,是不同的(如HOME),并尝试使用相同在脚本/ cron条目内检查它们是否工作。

如果仍然不能解决问题,那么我认为剩下的问题应该是在您的bitbucket凭证.netrc中保存用户名和密码。内容.netrc可能在cron环境中不可用。

相反,创建和set up an ssh keypair为您的帐户,让备份发生过ssh而不是https(它的更好,如果你生成这个步骤没有密码一个SSH密钥,以避免SSH密钥陷阱)。

一旦你已经安装SSH密钥,你会因此必须从.git/config文件项目根编辑现有源URL(或将要添加使用git remote add origin_ssh url新的远程origin_ssh SSH协议)。

请注意,https回购网址与https://[email protected]/user/repo.git相似,而ssh网址与[email protected]:user/repo.git相似。

PS:bitbucket,或者更确切地说git不是备份的理想解决方案,为了更好的备份策略存在大量的线程。此外,在调试时,每分钟运行一次crons(* * * * *),或者以相似的低频率运行以加快调试速度。

编辑

OP的评论说,设置PWD变量为他工作。

PWD =/my_django_project_path /助理/管理/命令到/ etc /环境

这是我早先提出,环境变量的一个可用在不存在在cron环境外壳。

一般来说,皇冠总是以减少的一组环境变量和权限运行,并设置正确的变量将使cron工作。

此外,由于您使用的是.netrc文件的权限,它是专门针对帐户,因此不会与任何其他帐户(包括sudo账户root)工作,除非你在配置相同的设置你其他帐户也是如此。

+0

感谢您的回复。直接和使用crontab从python脚本尝试printenv根本不起作用。不管输出的文件如何,都不会输出文件。如果从shell调用它,它将工作。也许这会是问题?我设法使用上述答案之一来使脚本工作,但我仍然对引起这种情况的原因感到好奇,所以50代表仍然可用。 –

+0

你是如何执行这项工作的?我安排了一个像'* * * * * printenv >>/home/mu/test_printenv.text',它对我很有用。输出在文件中。 –

+0

Ahhhh我正在使用>而不是>>。它与>>合作。我会检查输出并让你知道。 –

2

这使我想起一个非常令人沮丧的疑难杂症的。你的crontab文件最后有换行符吗?从man crontab:

... cron要求crontab中的每个条目以换行符结尾。 如果在crontab中的最后一个条目缺少换行符,cron将会 考虑的crontab(至少部分地)打破,拒绝安装 它。

+0

是的,我有一个换行符。我甚至增加了一个可以肯定的东西,但它仍然无法正常工作:)。 –

0

我不是在读书strace输出很不错,但我认为the one you posted表明你的程序调用git,正在等待其终止。你提到上传到到位桶,所以这里是一个瞎猜git试图推到一个SSH远程;当你自己运行它时,ssh-agent透明地验证你;但是当你以root身份运行它时,没有ssh-agent,因此git会提示输入ssh密码并等待输入。

尝试下sudo su,检查手动做git调用。

如果这没有帮助,你需要获取的git(或者不管它是什么,你实际上调用那里)输出。有关如何重定向标准输出和标准错误的详细信息,请检查documentation for the sh package

+0

我正在使用包含凭证的.netrc文件,因此git不应要求提供凭据。请检查更新后的问题。 –

+0

@ VladSchnakovszki对不起,但是当你不愿意调试和发布诊断时,很难为你提供帮助。很高兴知道你有一个'.netrc'。但很明显,你在那里开始一个流程,它不起作用,并且可以检查。正如我所说,你可以尝试在'sudo su'下手动执行'git'调用吗?你可以添加输出日志到你的'sh'调用吗? –

2

这也是在黑暗中拍摄 - 运行管理我们的团队已发出指令,通过cron的。我们从来没有想过要找出它们为什么片状,但经过很多发型后,我们直接调用python函数,而不是通过manage.py,事情自那时起就一直在嗡嗡作响。

+0

+1谢谢,这解决了这个问题。但是,我对造成这种行为的原因感兴趣,所以我会将这个信誉奖给那些发现它为什么会发生的人。 –