Cron没有运行django命令

我有一个Django脚本,应该在每天的特定时间运行。 我正在尝试使用crontab来实现这一点。 该脚本应该转储数据库,使用gzip将其归档并上传到bitbucket

以下是我的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 )也是非常好的。

读这个问题 ,我尝试了以下,没有成功:

将命令更改为:

 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文件的末尾。

更新:

在执行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) 

更新:

我正在使用下面的.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://%s@bitbucket.org/%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() 

更新:

我设法使用Chris Clark的build议直接调用脚本,而不是通过manage.py 。 不过,我仍然对造成这个问题的感兴趣,所以赏金仍然可用。

更新[已解决]:

将以下行添加到/etc/environment并以我的用户帐户而不是root用户身份运行它:

 PWD=/my_django_project_path/helpers/management/commands 

我仍然想知道为什么只有我的用户可以运行它,所以如果有人有解决scheme,请贡献。

由于python /my_django_project_path/manage.py database_bu 某些版本适用于您,这意味着问题出在您的cron environment ,或者您已经设置了cron而不是脚本本身的问题(例如文件大小被上传或网络连接不会造成问题)。

首先,你正在运行脚本

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

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

所以请尝试从当前用户调度您的cron作业。

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

这可能仍然不能完全运行cron作业。 在这种情况下,问题可能出现在两个地方 – 您的shell环境有一些cron环境中缺少的变量,或者您的.netrc文件没有被正确读取,或者两者都没有正确读取.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条目中使用相同的变量来检查它们是否工作。

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

相反,为你的帐户创建和设置一个ssh密钥对,让备份通过ssh而不是https (如果你在这一步没有通过密码生成一个ssh密钥,避免ssh-key的陷阱,那么它会更好)。

一旦你设置了ssh密钥,你将相应地必须从项目根.git/config文件编辑现有的源URL(或者使用git remote add origin_ssh url添加一个新的远程origin_ssh到ssh协议)。

需要注意的是, https url是https://user@bitbucket.org/user/repo.git而ssh则是git@bitbucket.org:user/repo.git

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

编辑

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

PWD = / my_django_project_path / helpers / management /命令到/ etc / environment

这是我之前提出的建议,在shell中可用的环境变量之一不在cron环境中。

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

此外,由于您正在使用.netrc文件进行权限设置,因此该帐户特定于您的帐户,因此这不适用于任何其他帐户(包括root帐户的sudo帐户),除非您在另一个帐户中将相同的设置配置为好。

这让我想起了一个非常令人沮丧的问题。 你的crontab文件最后有换行符吗? 从man crontab:

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

这也是黑暗中的一个镜头 – 我们的团队通过cron运行管理命令时遇到了问题。 我们从来没有打算去找出它们为什么是片状的,但是在经过大量的拉动之后,我们直接调用python函数,而不是通过manage.py来处理事情。

我不是很擅长阅读strace输出,但是我认为你发布的那个表明你的程序已经调用了git并且正在等待它的终止。 你提到上传到BitBucket,所以这是一个黑暗镜头git试图推送到一个SSH远程; 当你自己运行它时, ssh-agent透明地验证你; 但是当你以root身份运行它时,没有ssh-agent ,因此git会提示输入ssh密码并等待你的输入。

尝试在sudo su下手动执行git调用并检查。

如果这没有帮助,你需要得到git的输出(或者你在那里调用的任何东西)。 查看sh包的文档以获取有关如何重定向标准输出和标准错误的详细信息。