Cron ve virtualenv


227

Cron bir Django yönetim komutu çalıştırmak çalışıyorum. Projemi korumalı tutmak için virtualenv kullanıyorum.

Burada ve başka yerlerde sanal yönetim içinden çalışan yönetim komutlarını gösteren örnekler gördüm:

0 3 * * * source /home/user/project/env/bin/activate && /home/user/project/manage.py command arg

Ancak, syslog, görevin başlaması gerektiğinde bir girdi göstermesine rağmen, bu görev gerçekte hiçbir zaman çalışmaz (komut dosyasının günlük dosyası boştur). Çizgiyi kabuktan manuel olarak çalıştırırsam, beklendiği gibi çalışır.

Şu anda cron üzerinden çalıştırmak için komut almak, tek yolu komutları kırmak ve aptal bash sarıcı komut dosyası koymaktır:

#!/bin/sh
source /home/user/project/env/bin/activate
cd /home/user/project/
./manage.py command arg

DÜZENLE:

ars çalışan bir komut kombinasyonu ile geldi:

0 3 * * * cd /home/user/project && /home/user/project/env/bin/python /home/user/project/manage.py command arg

En azından benim durumumda, virtualenv için etkinleştirme komut dosyasını çağırmak hiçbir şey yapmadı. Bu, şovla devam ediyor.


Gördüğüm bir fark, komut dosyasının geçerli çalışma dizini olarak / home / user / project ile manage.py çalıştırmasıdır. Cron komutunuz ana dizininizle cwd olarak çalıştırılır. Belki günlük dosyası var mı?
rettops

Aslında günlük yolu kesinlikle tanımlanmıştır, komut dosyası çalışmadığı için oluşturulmamış / eklenmemiştir.
John-Scott

Cron sorunlarına hızlı ve kirli bir çözüm, ortamınızı (komutunuzun açıklanamayacak şekilde çalıştığı) envve exporthepsini crontab'dan çağırdığınız bir bash komut dosyası sarıcısına dökmektir.
jberryman

Yanıtlar:


250

Bunu python, sanal ortamınızda kullanarak yapabilirsiniz :

/home/my/virtual/bin/python /home/my/project/manage.py command arg

DÜZENLEME: Django projeniz PYTHONPATH içinde değilse, doğru dizine geçmeniz gerekir:

cd /home/my/project && /home/my/virtual/bin/python ...

Hatayı cron'dan günlüğe kaydetmeyi de deneyebilirsiniz:

cd /home/my/project && /home/my/virtual/bin/python /home/my/project/manage.py > /tmp/cronlog.txt 2>&1

Denenecek başka bir şey, manage.pykomut dosyanızda en üstte aynı değişikliği yapmaktır :

#!/home/my/virtual/bin/python

1
Bu da işe yaramıyor. Çalışmayan şeyler listeme koymayı unuttum. Evet, bu komutu kabukta manuel olarak çalıştırabilirim ama cron'dan çalışmaz.
John-Scott

Değiştirmeye mü ~tam yol ile? (Muhtemelen yaptınız, sadece emin olun ...)
ars

Ah, çalışan bir örnek buldun! Her kombinasyonu denedim ve virtualenv'i aktive etmenin hiçbir etkisi yok gibi görünüyor. PYTHONPATH .bashrc içinde ayarladım ama görünüşe göre bu cron tarafından kullanılmıyor? Cevabınızı vurgulamak için sorumu güncelleyeceğim.
John-Scott

Evet, cronun çok minimal bir ortamda koştuğunu unutmuştum. Genel öneri, işinizin ihtiyaç duyduğu ortamı kurmak için bash komut dosyaları yazmanızdır. Bash profilini doğrudan cron'da tedarik etmeyi deneyebilirsiniz, ancak bu, profilinizde ne olduğuna bağlı olarak ince hatalara yol açabilir (belki de bu tür ihtiyaçlar için ayrı ve minimal bir profiliniz varsa, iyi olur).
ars

7
Test etmenin iyi bir yolu / bin / sh komutunu çalıştırmak ve ardından komutunuzu oradan çalıştırmayı denemektir. En azından cron ile aynı ortam kurulumuna sahip olacaksınız.
Dick

98

sourceBir cronfile'dan çalıştırmak , cron'un /bin/shvarsayılan kabuğu olarak kullandığı için çalışmaz, bu desteklemez source. SHELL ortam değişkenini şu şekilde ayarlamanız gerekir /bin/bash:

SHELL=/bin/bash
*/10 * * * * root source /path/to/virtualenv/bin/activate && /path/to/build/manage.py some_command > /dev/null

/var/log/syslogHata ayrıntılarını kaydetmediği için bunun neden başarısız olduğunu tespit etmek zor . Herhangi bir cron hatası ile e-posta almak böylece kök kök takma en iyisi. Sadece kendinizi ekleyin /etc/aliasesve çalıştırın sendmail -bi.

Daha fazla bilgi için: http://codeinthehole.com/archives/43-Running-django-cronjobs-within-a-virtualenv.html

yukarıdaki bağlantı şu şekilde değiştirildi: https://codeinthehole.com/tips/running-django-cronjobs-within-a-virtualenv/


12
Veya '.' (dot command), / bin / sh tarafından desteklenmektedir. /path/to/virtualenv/bin/activate
Reed Sandberg

5
DavidWinterbottom, eğer gerçek adın buysa, sen benim kahramanımsın. Sh vs bash ve source dosyalarını bilmiyordum. Benim küçük bash-scripting dünya dostumun içine ışık tuttun. Teşekkürler.
joemurphy

Bir postactivatedosyanız varsa, yapmalısınızsource /path/to/virtualenv/bin/activate && source /path/to/virtualenv/bin/postactivate
dspacejs

1
Teşekkürler! Benim için bu, Gerald'ın kabul ettiği cevaptan ziyade çalışıyor.
Martin Becker

1
'kök' ne işe yarıyor? kimse açıklayabilir
adnanmuttaleb

19

Daha fazla bakma:

0 3 * * * /usr/bin/env bash -c 'cd /home/user/project && source /home/user/project/env/bin/activate && ./manage.py command arg' > /dev/null 2>&1

Genel yaklaşım:

* * * * * /usr/bin/env bash -c 'YOUR_COMMAND_HERE' > /dev/null 2>&1

Bu konuda güzellik değiştirmeniz gereken YAPMAYIN olduğu SHELLgelen crontab için değişkeni shiçinbash


13

Virtualenv kullanırken python cron işlerini çalıştırmanın tek doğru yolu, ortamı etkinleştirmek ve ardından kodunuzu çalıştırmak için ortamın python'unu çalıştırmaktır.

Bunu yapmanın bir yolu activate_thispython betiğinizde virtualenv'leri kullanmaktır , bkz: http://virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python

Başka bir çözüm, ortamın etkinleştirilmesi ve içine aktarılması da dahil olmak üzere tam komutu tekrarlamaktır /bin/bash. Bunu aşağıdakiler için düşünün /etc/crontab:

***** root echo 'source /env/bin/activate; python /your/script' | /bin/bash

1
Bunun tek doğru yol olduğuna dair fikir birliği olup olmadığına çok merak ediyorum.
Aaron Schumacher

1
Muhtemelen tek doğru yol budur. Ama işe yarayan başka yollar da var.
Will

4
Bu "tek doğru yol" değil. Ben başarılı bir sanalenv bir komut dosyası sadece '/ home / kullanıcı / klasör / env / bin / python' gibi sanalenv python ikili işaret cronjob işaret ederek. Çevreyi herhangi bir şekilde etkinleştirmeye gerek yoktur.
Canucklesandwich

Sanal ortamda özel PYTHONPATH kullanırsanız env / bin / python sizin için çalışmaz. Bu yüzden env / bin /
activ

1
Eğer PYTHONPATH set bağlıdır ve venv "aktive" gerektiren bir şekilde ayarlarsanız, bunu yanlış yapıyoruz

10

Virtualenv'e özel shebang'larla uğraşmak yerine, PATHcrontab'ın başına geçin .

Etkinleştirilmiş bir sanal ağda, bu üç komutu çalıştırın ve python komut dosyaları çalışmalıdır:

$ echo "PATH=$PATH" > myserver.cron
$ crontab -l >> myserver.cron
$ crontab myserver.cron

Crontab'ın ilk satırı şu şekilde görünmelidir:

PATH=/home/me/virtualenv/bin:/usr/bin:/bin:  # [etc...]

12
İyi bir çözüm değil. Daha sonra crontab'daki her python görevi, virtualenv'den ikili ile çalışacaktır. Bu ikiliyi sahte küresel bir piton yapmak, sanalenv'in amacına aykırıdır.
Victor Schröder

4

Benim için en iyi çözüm ikisine de

  • venv bin / dizinindeki python ikili dosyasını kullanın
  • python yolunu venv modülleri dizinini içerecek şekilde ayarlayın.

man pythonkabukta $PYTHONPATHveya python'da kabuktaki yolu değiştirereksys.path

Diğer cevaplar, kabuğu kullanarak bunu yapmak için fikirlerden bahsediyor. Python'dan betiğime şu satırları eklemek doğrudan cron'dan başarıyla çalıştırmamı sağlıyor.

import sys
sys.path.insert(0,'/path/to/venv/lib/python3.3/site-packages');

Etkileşimli bir oturumda nasıl göründüğü -

Python 3.3.2+ (default, Feb 28 2014, 00:52:16) 
[GCC 4.8.1] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import sys

>>> sys.path
['', '/usr/lib/python3.3', '/usr/lib/python3.3/plat-x86_64-linux-gnu', '/usr/lib/python3.3/lib-dynload']

>>> import requests
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named 'requests'   

>>> sys.path.insert(0,'/path/to/venv/modules/');

>>> import requests
>>>

4

Bunu eklemek istiyorum çünkü sorunu çözmek için biraz zaman harcadım ve cron ve virtualenv'de değişken kullanımı kombinasyonu için burada bir cevap bulamadım. Yani belki birine yardım eder.

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DIR_SMTH="cd /smth"
VENV=". venv/bin/activate"
CMD="some_python_bin do_something"
# m h  dom mon dow   command
0 * * * * $DIR_SMTH && $VENV && $CMD -k2 some_target >> /tmp/crontest.log 2>&1

Aşağıdaki gibi yapılandırıldığında iyi çalışmadı

DIR_SMTH = "cd / smth &&. Venv / bin / enable"

Teşekkür @davidwinterbottom , kamış-Sandberg @ ve @mkb doğru yönde verdiği için. Kabul edilen cevap, python'unuzun venv / bin dizininden başka bir python ikili çalıştırması gereken bir komut dosyasını çalıştırması gerekene kadar iyi çalışır.


0

Bu benim için iyi sonuç veren bir çözüm.

source /root/miniconda3/etc/profile.d/conda.sh && \
conda activate <your_env> && \
python <your_application> &

Ubuntu 18.04.3 LTS üzerinde Conda sürüm 4.7.12 ile miniconda kullanıyorum.

Yukarıdakileri bir betiğin içine yerleştirebilir ve crontab üzerinden sorunsuz çalıştırabilirim.


0

python betiği

from datetime import datetime                                                                                                                                                                
import boto   # check wheather its taking the virtualenv or not                                                                                                                                                                        
import sys                                                                                                                                                                                   
param1=sys.argv[1]     #Param                                                                                                                                                                                                                                                                                                                                                                    
myFile = open('appendtxt.txt', 'a')                                                                                                                                                      
myFile.write('\nAccessed on ' + param1+str(datetime.now())) 

Cron komutu

 */1 * * * *  cd /Workspace/testcron/ && /Workspace/testcron/venvcron/bin/python3  /Workspace/testcron/testcronwithparam.py param  

Yukarıdaki komutta

  • * / 1 * * * * - Her dakikayı çalıştır
  • cd / Workspace / testcron / - Python betiğinin yolu
  • / Çalışma alanı / testcron / venvcron / bin / python3 - Virtualenv yolu
  • Çalışma alanı / testcron / testcronwithparam.py - Dosya yolu
  • param - parametre
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.