Cron y virtualenv
Estoy tratando de ejecutar un comando de administración de Django desde cron. Estoy usando virtualenv para mantener mi proyecto aislado.
He visto ejemplos aquí y en otros lugares que muestran la ejecución de comandos de administración desde dentro de virtualenv como:
0 3 * * * source /home/user/project/env/bin/activate && /home/user/project/manage.py command arg
Sin embargo, aunque syslog muestra una entrada cuando la tarea debería haber comenzado, esta tarea nunca se ejecuta (el archivo de registro del script está vacío). Si corro la línea manualmente desde el shell, funciona como se esperaba.
La única manera actualmente puede obtener el comando para ejecutarse a través de cron, es romper los comandos y ponerlos en un script de envoltura bash tonto:
#!/bin/sh
source /home/user/project/env/bin/activate
cd /home/user/project/
./manage.py command arg
EDITAR:
A Ars se le ocurrió una combinación de comandos:
0 3 * * * cd /home/user/project && /home/user/project/env/bin/python /home/user/project/manage.py command arg
Al menos en mi caso, invocar el script activate para virtualenv no hizo nada. Esto funciona, así que con el programa.
7 answers
Debería poder hacer esto usando el python
en su entorno virtual:
/home/my/virtual/bin/python /home/my/project/manage.py command arg
EDITAR: Si tu proyecto django no está en PYTHONPATH, entonces necesitarás cambiar al directorio correcto:
cd /home/my/project && /home/my/virtual/bin/python ...
También puede intentar registrar el fallo desde cron:
cd /home/my/project && /home/my/virtual/bin/python /home/my/project/manage.py > /tmp/cronlog.txt 2>&1
Otra cosa a intentar es hacer el mismo cambio en su script manage.py
en la parte superior:
#!/home/my/virtual/bin/python
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-09 22:27:32
Ejecutar source
desde un cronfile no funcionará ya que cron usa /bin/sh
como su shell predeterminado, que no soporta source
. Necesita establecer la variable de entorno SHELL como /bin/bash
:
SHELL=/bin/bash
*/10 * * * * root source /path/to/virtualenv/bin/activate && /path/to/build/manage.py some_command > /dev/null
Es difícil detectar por qué esto falla ya que /var/log/syslog
no registra los detalles del error. Lo mejor es que te pongas un alias en root para que te envíen un correo electrónico con cualquier error de cron. Simplemente agrégate a /etc/aliases
y ejecuta sendmail -bi
.
Más información aqui: http://codeinthehole.com/archives/43-Running-django-cronjobs-within-a-virtualenv.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-11 19:33:35
En lugar de perder el tiempo con shebangs específicos de virtualenv, simplemente anteponga PATH
en el crontab.
Desde un virtualenv activado, ejecute estos tres comandos y los scripts de python deberían funcionar:
$ echo "PATH=$PATH" > myserver.cron
$ crontab -l >> myserver.cron
$ crontab myserver.cron
La primera línea del crontab debería verse así:
PATH=/home/me/virtualenv/bin:/usr/bin:/bin: # [etc...]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-12 04:42:01
La única forma correcta de ejecutar trabajos cron de python cuando se utiliza un virtualenv es activar el entorno y luego ejecutar python del entorno para ejecutar su código.
Una forma de hacer esto es usar el activate_this
de virtualenv en su script python, vea: http://virtualenv.readthedocs.org/en/latest/userguide.html#using-virtualenv-without-bin-python
Otra solución está haciendo eco del comando completo, incluyendo la activación del entorno y la tubería en /bin/bash
. Considere esto para su /etc/crontab
:
***** root echo 'source /env/bin/activate; python /your/script' | /bin/bash
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-27 23:34:44
No busques más:
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
Enfoque genérico:
* * * * * /usr/bin/env bash -c 'YOUR_COMMAND_HERE' > /dev/null 2>&1
La belleza de esto es que NO necesita cambiar la variable SHELL
para crontab de sh
a bash
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-27 21:32:19
La mejor solución para mí fue tanto
- utilice el binario python en el directorio venv bin/
- establecer la ruta de python para incluir el directorio de módulos venv.
man python
menciona modificar la ruta en shell en $PYTHONPATH
o en python con sys.path
Otras respuestas mencionan ideas para hacer esto usando el shell. Desde python, agregar las siguientes líneas a mi script me permite ejecutarlo con éxito directamente desde cron.
import sys
sys.path.insert(0,'/path/to/venv/lib/python3.3/site-packages');
Así es como se ve en un sesión interactiva --
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
>>>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-25 08:00:09
Me gustaría agregar esto porque pasé algún tiempo resolviendo el problema y no encontré una respuesta aquí para la combinación de uso de variables en cron y virtualenv. Así que tal vez ayude a alguien.
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
No funcionó bien cuando se configuró como
DIR_SMTH="cd /smth && . venv / bin / activate "
Gracias @davidwinterbottom, @reed-sandberg y @mkb para dar la dirección correcta. La respuesta aceptada realmente funciona bien hasta que su python necesita ejecutar un script que tiene que ejecutar otro binario python desde el directorio venv/bin.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-08 15:26:50