2014-03-03 346 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謝謝,這解決了這個問題。但是,我對造成這種行爲的原因感興趣,所以我會將這個信譽獎給那些發現它爲什麼會發生的人。 –